Path: utzoo!utgpu!news-server.csri.toronto.edu!mailrus!uunet!mcsun!ukc!icdoc!qmw-cs!liam From: liam@cs.qmw.ac.uk (William Roberts) Newsgroups: comp.unix.aux Subject: Re: How do you read symbols in /dev/kmem when nlist won't work Summary: problem solved by unpleasant means Keywords: kernel, nlist Message-ID: <2346@sequent.cs.qmw.ac.uk> Date: 7 Jun 90 19:44:47 GMT References: <1990Jun6.003947.27323@portia.Stanford.EDU> <2343@sequent.cs.qmw.ac.uk> Organization: Computer Science Dept, QMW, University of London, UK. Lines: 225 Got it! The common factor between the things that didn't work with my version of nlist.h (some of which have worked for me in other A/UX programs after I had converted to dynamic initialisation into the n_name array) is THEY ARE LESS THAN 9 CHARACTERS LONG You guessed it - the compiler puts the symbol directly into the entry if it is small enough to fit, only using the string table if the name is too long. Damn! Apple, please can you fix nlist.c (aka syment()) so that it checks the length of new-style labels passed in as a parameter and is prepared to be flexible about matching oldstyle with newstyle. I've reworked my nlist.h file but it is now terribly ugly. The revised nlist.h and nlist_test.c files are appended to this message, and the compilation and test run go as follows: # cc -o nlist_test nlist_test.c "nlist_test.c", line 25: warning: non-null byte ignored in string initializer "nlist_test.c", line 26: warning: non-null byte ignored in string initializer # nlist_test First, the long names... symbol rthashsize has value 0x110087c0 (type 0) symbol icmp_input has value 0x1004990e (type 0) symbol icmproto has value 0x0 (type 0) symbol avenrun has value 0x0 (type 0) symbol clstat has value 0x0 (type 0) symbol icmpstat has value 0x0 (type 0) Then the short names... symbol icmproto has value 0x11008d20 (type 0) symbol avenrun has value 0x12011440 (type 0) symbol clstat has value 0x1201c444 (type 0) symbol icmpstat has value 0x12017c34 (type 0) symbol rthashsi has value 0x0 (type 0) symbol icmp_inp has value 0x0 (type 0) # You guessed, it doesn't try to do anything clever about matching just the first 8 characters either (probably a good thing). Hope this helps you fix your problems with xload... # This is a shar archive. # Remove everything above and including the cut line. # Then run the rest of the file through sh. #--------cut--------cut--------cut--------cut--------cut-------- #! /bin/sh # shar: Shell Archiver # Run the following with /bin/sh to create: # nlist.h # nlist_test.c # This archive created: Thu Jun 7 20:42:47 WET DST 1990 echo shar: extracting "nlist.h" '('2365 chars')' if test -f nlist.h then echo shar: will not overwrite existing file "nlist.h" else cat << \SHAR_EOF > nlist.h /* Imitation nlist.h file for rough and ready compatibility between * the BSD style of doing things and SysV * * Use this file in preference to a.out.h for BSD files, though * you might want to convert over entirely to the SysV scheme. * * William Roberts QMW, University of London 7th June 1990 */ #ifndef __NLIST__ #define __NLIST__ struct nlist_syment_long { long n_zeroes; /* must be 0 */ char *n_name; /* offset into string table */ long n_value; /* value of symbol */ short n_scnum; /* section number */ unsigned short n_type; /* type and derived type */ char n_sclass; /* storage class */ char n_numaux; /* number of aux. entries */ }; #define SYMNMLEN 8 struct nlist_syment_short { char n_name[SYMNMLEN]; /* the symbol name */ long n_value; /* value of symbol */ short n_scnum; /* section number */ unsigned short n_type; /* type and derived type */ char n_sclass; /* storage class */ char n_numaux; /* number of aux. entries */ }; #define nlist syment #define NLIST_LONG_ENTRY(s) {0, (s)} #define NLIST_SHORT_ENTRY(s) {(s)} /* The tradition BSD cliche of * * struct nlist nl[] = { * { "longname1" }, * { "name2" }, * { 0 } * } * * should be converted to * * struct nlist_syment_long nl_long[] = { * NLIST_LONG_ENTRY("longname1"), * NLIST_LONG_ENTRY(0) * }; * * struct nlist_syment_short nl_short[] = { * NLIST_SHORT_ENTRY("name2"), * NLIST_SHORT_ENTRY(0) * }; * * The reason for having two different structures is that the brain-damaged * linker insists on saving a few bytes for short symbols by using the * other variant, but the syment routine (equivalent to nlist) will * only compare like with like. * * Note that you probably won't get away with using an empty string as the * end marker rather than NULL. * * You need the struct nlist_syments as defined above otherwise you will get * the struct syment which includes a union and so can't be given a * static initialiser. */ #endif SHAR_EOF if test 2365 -ne `wc -c < nlist.h` then echo shar: error transmitting "nlist.h" '('should be 2365 chars')' else echo nlist.h fi fi echo shar: extracting "nlist_test.c" '('1683 chars')' if test -f nlist_test.c then echo shar: will not overwrite existing file "nlist_test.c" else cat << \SHAR_EOF > nlist_test.c #include #include "nlist.h" struct nlist_syment_long Nl_long[] = { NLIST_LONG_ENTRY("rthashsize"), NLIST_LONG_ENTRY("icmp_input"), /* the rest won't work because the COFF file will have them as * short form entries... */ NLIST_LONG_ENTRY("icmproto"), NLIST_LONG_ENTRY("avenrun"), NLIST_LONG_ENTRY("clstat"), NLIST_LONG_ENTRY("icmpstat"), NLIST_LONG_ENTRY(0) }; struct nlist_syment_short Nl_short[] = { NLIST_SHORT_ENTRY("icmproto"), NLIST_SHORT_ENTRY("avenrun"), NLIST_SHORT_ENTRY("clstat"), NLIST_SHORT_ENTRY("icmpstat"), /* These are long entries - the compiler will issue a warning when * it truncates the initialiser and then they won't match with the * long form entries in the COFF file. */ NLIST_SHORT_ENTRY("rthashsize"), NLIST_SHORT_ENTRY("icmp_input"), NLIST_SHORT_ENTRY(0) }; main() { int i; printf("First, the long names...\n"); i = nlist("/unix", Nl_long); if (i < 0) { perror("nlist"); } else { for (i=0; Nl_long[i].n_name != 0; i++) { printf("symbol %s has value 0x%x (type %d)\n", Nl_long[i].n_name, Nl_long[i].n_value, Nl_long[i].n_type); } } /* Note that the "run off end" test for Nl_short is * different, and that we need to restrict the string length * to a maximum of 8 characters when printing it out */ printf("\nThen the short names...\n"); i = nlist("/unix", Nl_short); if (i < 0) { perror("nlist"); } else { for (i=0; Nl_short[i].n_name[0] != 0; i++) { printf("symbol %.8s has value 0x%x (type %d)\n", Nl_short[i].n_name, Nl_short[i].n_value, Nl_short[i].n_type); } } } SHAR_EOF if test 1683 -ne `wc -c < nlist_test.c` then echo shar: error transmitting "nlist_test.c" '('should be 1683 chars')' else echo nlist_test.c fi fi # End of shar archive exit 0 -- William Roberts ARPA: liam@cs.qmw.ac.uk Queen Mary & Westfield College UUCP: liam@qmw-cs.UUCP Mile End Road AppleLink: UK0087 LONDON, E1 4NS, UK Tel: 071-975 5250 (Fax: 081-980 6533)