From c595699ca75f88245cdecb86c91d53d11bbf69f6 Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Wed, 26 Sep 2012 18:29:11 +0200 Subject: [PATCH] unstack, sort: cleanup and improvement lets unstack (a) know about in-kernel ipc entry points and (b) be able handle >2GB symbol offsets. . sort: add -x for hex numerical sort . unstack: gnm is obsolete . unstack: datasizes is obsolete (use nm --size-sort instead) . unstack: add ipc entry points read from procfs (hex) . unstack: use sort -x to sort symbol order so the procfs ones are sorted independent of position and original ordering --- commands/sort/sort.c | 26 ++++++++++++++++ commands/unstack/unstack.sh | 61 ++++++++++++++++--------------------- man/man1/sort.1 | 5 ++- 3 files changed, 56 insertions(+), 36 deletions(-) diff --git a/commands/sort/sort.c b/commands/sort/sort.c index e8497d433..5481d2779 100644 --- a/commands/sort/sort.c +++ b/commands/sort/sort.c @@ -96,6 +96,7 @@ typedef struct { BOOL fold_case; BOOL ascii; BOOL numeric; + BOOL hexmode; } FIELD; /* Field declarations. A total of FILEDS_LIMIT is allowed */ @@ -150,6 +151,7 @@ char *skip_fields(char *str, int nf); int compare(char *el1, char *el2); int cmp(unsigned char *el1, unsigned char *el2, FIELD * field); int digits(char *str1, char *str2, BOOL check_sign); +int hexits(char *str1, char *str2); void files_merge(int file_cnt); void merge(int start_file, int limit_file); void put_line(char *line); @@ -250,6 +252,10 @@ register FIELD *field; field->numeric = TRUE; field->blanks = TRUE; break; + case 'x': + field->hexmode = TRUE; + field->blanks = TRUE; + break; case 'r': /* Reverse comparisons */ field->reverse = TRUE; break; @@ -761,6 +767,8 @@ FIELD *field; } if (field->numeric) /* Compare numeric */ return digits((char *) el1, (char *) el2, TRUE); + if (field->hexmode) /* Compare hex */ + return hexits((char *) el1, (char *) el2); for (;;) { while (*el1 == *el2) { @@ -811,6 +819,24 @@ FIELD *field; /* NOTREACHED */ } +int hexits(char *str1, char *str2) +{ + unsigned long v1, v2; + int r1, r2; + r1 = sscanf(str1, "0x%lx", &v1); + r2 = sscanf(str2, "0x%lx", &v2); + + /* ordering based on reasonable hex number */ + if(r1 == 1 && r2 != 1) return HIGHER; + if(r1 != 1 && r2 == 1) return LOWER; + if(r1 != 1 && r2 != 1) return SAME; + + if(v1 > v2) return HIGHER; + if(v1 < v2) return LOWER; + + return SAME; +} + /* * Digits compares () the two strings that point to a number of digits followed * by an optional decimal point. diff --git a/commands/unstack/unstack.sh b/commands/unstack/unstack.sh index bb781c624..118913216 100644 --- a/commands/unstack/unstack.sh +++ b/commands/unstack/unstack.sh @@ -3,17 +3,23 @@ # Look at /usr/pkg/bin first in case there is an old nm in /usr/bin PATH=/usr/pkg/bin:$PATH:/usr/gnu/bin +# Does procfs give us some extra 'symbols'? +IPCVECS=/proc/ipcvecs +if [ -f $IPCVECS ] +then EXTRANM="cat $IPCVECS" +fi + # Check usage if [ $# -lt 1 ] then echo "Usage: unstack [0x... [0x... ] ]" - echo " datasizes " exit 1 fi # Check invocation mode case "`basename $0`" in datasizes) - mode=data + echo "datasizes is obsolete; please use nm --size-sort instead." + exit 1 ;; unstack) mode=stack @@ -28,46 +34,31 @@ esac executable=$1 shift -# gnu nm can be gnm or nm -if which gnm >/dev/null 2>&1 -then GNM=gnm -else GNM=nm +if ! which gawk >/dev/null 2>&1 +then echo "Please install gawk." + exit 1 fi -# Invoke gnu nm or ack nm? -if file $executable | grep NSYM >/dev/null 2>&1 -then NM="$GNM --radix=d" -elif file $executable | grep ELF >/dev/null 2>&1 -then NM="$GNM --radix=d" -else NM="acknm -d" +# Invoke binutils nm or ack nm? +if file $executable | grep ELF >/dev/null 2>&1 +then NM="nm" +else NM="acknm" fi -# Invoked as unstack? -if [ $mode = stack ] -then - while [ $# -gt 0 ] - do dec="`printf %d $1`" - $NM -n $executable | grep ' [Tt] [^.]' | awk ' - { if($1 > '$dec') { printf "%s+0x%x\n", name, '$dec'-offset; exit } - name=$3; offset=$1 - }' - shift - done +SYMLIST=/tmp/unstack.$$ - exit 0 -fi +# store sorted, filtered nm output once +( $NM $executable ; $EXTRANM ) | sed 's/^/0x/' | sort -x | grep ' [Tt] [^.]' >$SYMLIST -# Invoked as datasizes? -if [ $mode = data ] -then - $NM -n $executable | - grep ' [bBdD] [^.]' | awk '{ if (lastpos) printf "%10ld kB %s\n", ($1-lastpos)/1024, lastname; lastpos=$1; lastname=$3 }' | sort -n +while [ $# -gt 0 ] +do gawk <$SYMLIST --non-decimal-data -v symoffset=$1 ' + { if($1 > symoffset) { printf "%s+0x%x\n", name, symoffset-prevoffset; exit } + name=$3; prevoffset=$1; + }' + shift +done - exit 0 -fi - -# Can't happen. -echo "Impossible invocation." +rm -f $SYMLIST exit 1 diff --git a/man/man1/sort.1 b/man/man1/sort.1 index 1bc30edd9..9d276ae9c 100644 --- a/man/man1/sort.1 +++ b/man/man1/sort.1 @@ -35,7 +35,10 @@ sort \- sort a file of ASCII lines # Merge presorted files .TP 5 .B \-n -# Numeric sort order +# Numeric sort order (decimal) +.TP 5 +.B \-x +# Numeric sort order (hex) .TP 5 .B \-o # Next argument is output file