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
This commit is contained in:
Ben Gras 2012-09-26 18:29:11 +02:00
parent 2cdbb3041d
commit c595699ca7
3 changed files with 56 additions and 36 deletions

View file

@ -96,6 +96,7 @@ typedef struct {
BOOL fold_case; BOOL fold_case;
BOOL ascii; BOOL ascii;
BOOL numeric; BOOL numeric;
BOOL hexmode;
} FIELD; } FIELD;
/* Field declarations. A total of FILEDS_LIMIT is allowed */ /* 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 compare(char *el1, char *el2);
int cmp(unsigned char *el1, unsigned char *el2, FIELD * field); int cmp(unsigned char *el1, unsigned char *el2, FIELD * field);
int digits(char *str1, char *str2, BOOL check_sign); int digits(char *str1, char *str2, BOOL check_sign);
int hexits(char *str1, char *str2);
void files_merge(int file_cnt); void files_merge(int file_cnt);
void merge(int start_file, int limit_file); void merge(int start_file, int limit_file);
void put_line(char *line); void put_line(char *line);
@ -250,6 +252,10 @@ register FIELD *field;
field->numeric = TRUE; field->numeric = TRUE;
field->blanks = TRUE; field->blanks = TRUE;
break; break;
case 'x':
field->hexmode = TRUE;
field->blanks = TRUE;
break;
case 'r': /* Reverse comparisons */ case 'r': /* Reverse comparisons */
field->reverse = TRUE; field->reverse = TRUE;
break; break;
@ -761,6 +767,8 @@ FIELD *field;
} }
if (field->numeric) /* Compare numeric */ if (field->numeric) /* Compare numeric */
return digits((char *) el1, (char *) el2, TRUE); return digits((char *) el1, (char *) el2, TRUE);
if (field->hexmode) /* Compare hex */
return hexits((char *) el1, (char *) el2);
for (;;) { for (;;) {
while (*el1 == *el2) { while (*el1 == *el2) {
@ -811,6 +819,24 @@ FIELD *field;
/* NOTREACHED */ /* 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 * Digits compares () the two strings that point to a number of digits followed
* by an optional decimal point. * by an optional decimal point.

View file

@ -3,17 +3,23 @@
# Look at /usr/pkg/bin first in case there is an old nm in /usr/bin # Look at /usr/pkg/bin first in case there is an old nm in /usr/bin
PATH=/usr/pkg/bin:$PATH:/usr/gnu/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 # Check usage
if [ $# -lt 1 ] if [ $# -lt 1 ]
then echo "Usage: unstack <executable> [0x... [0x... ] ]" then echo "Usage: unstack <executable> [0x... [0x... ] ]"
echo " datasizes <executable>"
exit 1 exit 1
fi fi
# Check invocation mode # Check invocation mode
case "`basename $0`" in case "`basename $0`" in
datasizes) datasizes)
mode=data echo "datasizes is obsolete; please use nm --size-sort instead."
exit 1
;; ;;
unstack) unstack)
mode=stack mode=stack
@ -28,46 +34,31 @@ esac
executable=$1 executable=$1
shift shift
# gnu nm can be gnm or nm if ! which gawk >/dev/null 2>&1
if which gnm >/dev/null 2>&1 then echo "Please install gawk."
then GNM=gnm exit 1
else GNM=nm
fi fi
# Invoke gnu nm or ack nm? # Invoke binutils nm or ack nm?
if file $executable | grep NSYM >/dev/null 2>&1 if file $executable | grep ELF >/dev/null 2>&1
then NM="$GNM --radix=d" then NM="nm"
elif file $executable | grep ELF >/dev/null 2>&1 else NM="acknm"
then NM="$GNM --radix=d"
else NM="acknm -d"
fi fi
# Invoked as unstack? SYMLIST=/tmp/unstack.$$
if [ $mode = stack ]
then # store sorted, filtered nm output once
while [ $# -gt 0 ] ( $NM $executable ; $EXTRANM ) | sed 's/^/0x/' | sort -x | grep ' [Tt] [^.]' >$SYMLIST
do dec="`printf %d $1`"
$NM -n $executable | grep ' [Tt] [^.]' | awk ' while [ $# -gt 0 ]
{ if($1 > '$dec') { printf "%s+0x%x\n", name, '$dec'-offset; exit } do gawk <$SYMLIST --non-decimal-data -v symoffset=$1 '
name=$3; offset=$1 { if($1 > symoffset) { printf "%s+0x%x\n", name, symoffset-prevoffset; exit }
name=$3; prevoffset=$1;
}' }'
shift shift
done done
exit 0 rm -f $SYMLIST
fi
# 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
exit 0
fi
# Can't happen.
echo "Impossible invocation."
exit 1 exit 1

View file

@ -35,7 +35,10 @@ sort \- sort a file of ASCII lines
# Merge presorted files # Merge presorted files
.TP 5 .TP 5
.B \-n .B \-n
# Numeric sort order # Numeric sort order (decimal)
.TP 5
.B \-x
# Numeric sort order (hex)
.TP 5 .TP 5
.B \-o .B \-o
# Next argument is output file # Next argument is output file