############################################################################ # # File: loadmap.icn # # Subject: Program to show load map of UNIX object file # # Author: Stephen B. Wampler # # Date: December 13, 1985 # ############################################################################ # # This file is in the public domain. # ############################################################################ # # This program produces a formatted listing of selected symbol classes # from a compiled file. The listing is by class, and gives the # name, starting address, and length of the region associated with # each symbol. # # The options are: # # -a Display the absolute symbols. # # -b Display the BSS segment symbols. # # -c Display the common segment symbols. # # -d Display the data segment symbols. # # -t Display the text segment symbols. # # -u Display the undefined symbols. # # If no options are specified, -t is assumed. # # If the address of a symbol cannot be determined, ???? is given in # its place. # ############################################################################ # # Notes: # # The size of the last region in a symbol class is suspect and is # usually given as rem. # # Output is not particularly exciting on a stripped file. # ############################################################################ # # Requires: UNIX # ############################################################################ record entry(name,address) procedure main(args) local maptype, arg, file, nm, ldmap, tname, line, text, data, bss local SPACE, COLON, DIGITS, HEXDIGITS, usize, address, name, nmtype initial { if *args = 0 then stop("usage: loadmap [-t -d -b -u -a -c -l] file") SPACE := '\t ' COLON := ':' DIGITS := '0123456789' HEXDIGITS := DIGITS ++ 'abcdef' ldmap := table(6) ldmap["u"] := [] ldmap["d"] := [] ldmap["a"] := [] ldmap["b"] := [] ldmap["t"] := [] ldmap["c"] := [] tname := table(6) tname["u"] := "Undefined symbols" tname["a"] := "Absolute locations" tname["t"] := "Text segment symbols" tname["d"] := "Data segment symbols" tname["b"] := "BSS segment symbols" tname["c"] := "Common symbols" nmtype := "nm -gno " } maptype := "" every arg := !args do if arg[1] ~== "-" then file := arg else if arg == "-l" then nmtype := "nm -no " else if arg[1] == "-" then maptype ||:= (!"ltdbuac" == arg[2:0]) | stop("usage: loadmap [-t -d -b -u -a -c -l] file") maptype := if *maptype = 0 then "t" else string(cset(maptype)) write("\n",file,"\n") usize := open("size " || file,"rp") | stop("loadmap: cannot execute size") !usize ? { writes("Text space: ",right(text := tab(many(DIGITS)),6)," ") move(1) writes("Initialized Data: ",right(data := tab(many(DIGITS)),6)," ") move(1) write("Uninitialized Data: ",right(bss := tab(many(DIGITS)),6)) } close(usize) nm := open(nmtype || file,"rp") | stop("loadmap: cannot execute nm") every line := !nm do line ? { tab(upto(COLON)) & move(1) address := integer("16r" || tab(many(HEXDIGITS))) | "????" tab(many(SPACE)) type := map(move(1)) tab(many(SPACE)) name := tab(0) if find(type,maptype) then put(ldmap[type],entry(name,address)) } every type := !maptype do { if *ldmap[type] > 0 then { write("\n\n\n") write(tname[type],":") write() show(ldmap[type],(type == "t" & text) | (type == "d" & data) | (type == "b" & bss) | &null, ldmap[type][1].address) } } end procedure show(l,ssize,base) local i1, i2, nrows static ncols initial ncols := 3 write(repl(repl(" ",3) || left("name",9) || right("addr",7) || right("size",6),ncols)) write() nrows := (*l + (ncols - 1)) / ncols every i1 := 1 to nrows do { every i2 := i1 to *l by nrows do writes(repl(" ",3),left(l[i2].name,9),right(l[i2].address,7), right(area(l[i2 + 1].address,l[i2].address) | if /ssize then "rem" else base + ssize - l[i2].address,6)) write() } return end procedure area(high,low) if integer(low) & integer(high) then return high - low else return "????" end