this is to force invocations of these utils for ack to be explicitly named such, so in the future binutils can be installed in /usr/pkg without the g- prefix.
		
			
				
	
	
		
			227 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			227 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/* nm - print name list.		Author: Dick van Veen */
 | 
						|
 | 
						|
/* Dick van Veen: veench@cs.vu.nl */
 | 
						|
 | 
						|
#include <sys/types.h>
 | 
						|
#include <a.out.h>
 | 
						|
#include <fcntl.h>
 | 
						|
#include <unistd.h>
 | 
						|
#include <stdlib.h>
 | 
						|
#include <string.h>
 | 
						|
#include <stdio.h>
 | 
						|
 | 
						|
/* Read the name list in memory, sort it, and print it.  */
 | 
						|
 | 
						|
/* Nm [-gnopru] [file] ...
 | 
						|
 *
 | 
						|
 * flags:
 | 
						|
 *	-d	address in decimal
 | 
						|
 *	-g	print only external symbols.
 | 
						|
 *	-n	sort numerically rather than alphabetically.
 | 
						|
 *	-o	prepend file name to each line rather than only once.
 | 
						|
 *	-p	don't sort, pint n symbol-table order.
 | 
						|
 *	-r	sort in reverse order.
 | 
						|
 *	-u	print only undefined symbols.
 | 
						|
 *
 | 
						|
 *	-	when no file name is present, a.out is assumed.
 | 
						|
 *
 | 
						|
 *	NOTE:	no archives are supported because assembly files don't
 | 
						|
 *		have symbol tables.
 | 
						|
 *
 | 
						|
 */
 | 
						|
 | 
						|
#define A_OUT		"a.out"
 | 
						|
 | 
						|
int d_flag;
 | 
						|
int g_flag;
 | 
						|
int n_flag;
 | 
						|
int o_flag;
 | 
						|
int p_flag;
 | 
						|
int r_flag;
 | 
						|
int u_flag;
 | 
						|
 | 
						|
char io_buf[BUFSIZ];		/* io buffer */
 | 
						|
struct exec header;		/* header of a.out file */
 | 
						|
int stbl_elems;			/* #elements in symbol table */
 | 
						|
 | 
						|
_PROTOTYPE(int main, (int argc, char **argv));
 | 
						|
_PROTOTYPE(int nm_sort, (const void *tmp_stbl1, const void *tmp_stbl2));
 | 
						|
_PROTOTYPE(void nm, (char *file));
 | 
						|
_PROTOTYPE(int read_header, (int fd));
 | 
						|
_PROTOTYPE(void nm_print, (char *file, struct nlist *stbl));
 | 
						|
 | 
						|
int main(argc, argv)
 | 
						|
int argc;
 | 
						|
char **argv;
 | 
						|
{
 | 
						|
  argv++;
 | 
						|
  while (*argv != 0 && **argv == '-') {
 | 
						|
	*argv += 1;
 | 
						|
	while (**argv != '\0') {
 | 
						|
		switch (**argv) {
 | 
						|
		    case 'd':	d_flag = 1;	break;
 | 
						|
		    case 'g':	g_flag = 1;	break;
 | 
						|
		    case 'n':	n_flag = 1;	break;
 | 
						|
		    case 'o':	o_flag = 1;	break;
 | 
						|
		    case 'p':	p_flag = 1;	break;
 | 
						|
		    case 'r':	r_flag = 1;	break;
 | 
						|
		    case 'u':	u_flag = 1;	break;
 | 
						|
		    default:
 | 
						|
			fprintf(stderr, "illegal flag: -%c\n", **argv);
 | 
						|
			exit(-1);
 | 
						|
		}
 | 
						|
		*argv += 1;
 | 
						|
	}
 | 
						|
	argv++;
 | 
						|
  }
 | 
						|
  setbuf(stdin, io_buf);
 | 
						|
  if (*argv == 0)
 | 
						|
	nm(A_OUT);
 | 
						|
  else
 | 
						|
	while (*argv != 0) {
 | 
						|
		nm(*argv);
 | 
						|
		argv++;
 | 
						|
	}
 | 
						|
  return(0);
 | 
						|
}
 | 
						|
 | 
						|
int nm_sort(tmp_stbl1, tmp_stbl2)
 | 
						|
_CONST void *tmp_stbl1, *tmp_stbl2;
 | 
						|
{
 | 
						|
 | 
						|
  struct nlist *stbl1 = (struct nlist *)tmp_stbl1;
 | 
						|
  struct nlist *stbl2 = (struct nlist *)tmp_stbl2;
 | 
						|
  int cmp;
 | 
						|
 | 
						|
  if (n_flag) {			/* sort numerically */
 | 
						|
	if ((stbl1->n_sclass & N_SECT) <
 | 
						|
	    (stbl2->n_sclass & N_SECT))
 | 
						|
		cmp = -1;
 | 
						|
	else if ((stbl1->n_sclass & N_SECT) >
 | 
						|
		 (stbl2->n_sclass & N_SECT))
 | 
						|
		cmp = 1;
 | 
						|
	else if (stbl1->n_value < stbl2->n_value)
 | 
						|
		cmp = -1;
 | 
						|
	else if (stbl1->n_value > stbl2->n_value)
 | 
						|
		cmp = 1;
 | 
						|
	else
 | 
						|
		cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
 | 
						|
  } else {
 | 
						|
	cmp = strncmp(stbl1->n_name, stbl2->n_name, (size_t)8);
 | 
						|
	if (cmp == 0) {
 | 
						|
		if (stbl1->n_value < stbl2->n_value)
 | 
						|
			cmp = -1;
 | 
						|
		else if (stbl1->n_value > stbl2->n_value)
 | 
						|
			cmp = 1;
 | 
						|
	}
 | 
						|
  }
 | 
						|
 | 
						|
  if (r_flag) cmp = -cmp;	/* reverse sort */
 | 
						|
  return(cmp);
 | 
						|
}
 | 
						|
 | 
						|
void nm(file)
 | 
						|
char *file;
 | 
						|
{
 | 
						|
  struct nlist *stbl;
 | 
						|
  int fd;
 | 
						|
 | 
						|
  fd = open(file, O_RDONLY);
 | 
						|
  if (fd == -1) {
 | 
						|
	fprintf(stderr, "can't open %s\n", file);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  if (read_header(fd)) {
 | 
						|
	fprintf(stderr, "%s: no executable file\n", file);
 | 
						|
	close(fd);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  if (header.a_syms == 0) {
 | 
						|
	close(fd);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  if ((size_t) header.a_syms != header.a_syms) {
 | 
						|
	fprintf(stderr, "%s: symbol table too large to allocate\n", file);
 | 
						|
	close(fd);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  if ((int) header.a_syms != header.a_syms) {
 | 
						|
	/* This is necessary because we are too lazy to iterate the read. */
 | 
						|
	fprintf(stderr, "%s: symbol table too large to read\n", file);
 | 
						|
	close(fd);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  stbl = (struct nlist *) malloc((size_t) header.a_syms);
 | 
						|
  if (stbl == NULL) {
 | 
						|
	fprintf(stderr, "%s: can't allocate symbol table\n", file);
 | 
						|
	close(fd);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  if (read(fd, (char *) stbl, (unsigned) header.a_syms) != header.a_syms) {
 | 
						|
	fprintf(stderr, "%s: can't read symbol table\n", file);
 | 
						|
	free(stbl);
 | 
						|
	close(fd);
 | 
						|
	return;
 | 
						|
  }
 | 
						|
  stbl_elems = (int) header.a_syms / sizeof(struct nlist);
 | 
						|
  if (!p_flag) qsort(stbl, (size_t)stbl_elems, sizeof(struct nlist), nm_sort);
 | 
						|
  nm_print(file, stbl);
 | 
						|
  free(stbl);
 | 
						|
  close(fd);
 | 
						|
}
 | 
						|
 | 
						|
int read_header(fd)
 | 
						|
int fd;
 | 
						|
{
 | 
						|
  if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec))
 | 
						|
	return(1);
 | 
						|
  if (BADMAG(header)) return(1);
 | 
						|
  lseek(fd, A_SYMPOS(header), SEEK_SET);
 | 
						|
 | 
						|
  return(0);
 | 
						|
}
 | 
						|
 | 
						|
void nm_print(file, stbl)
 | 
						|
char *file;
 | 
						|
register struct nlist *stbl;
 | 
						|
{
 | 
						|
  struct nlist *last;
 | 
						|
  char name[9];
 | 
						|
  int n_sclass;
 | 
						|
  char type;
 | 
						|
 | 
						|
  name[8] = '\0';
 | 
						|
  if (!o_flag) printf("%s:\n", file);
 | 
						|
  for (last = &stbl[stbl_elems]; stbl != last; stbl++) {
 | 
						|
	if (g_flag && (stbl->n_sclass & N_CLASS) != C_EXT) continue;
 | 
						|
	if (u_flag && (stbl->n_sclass & N_SECT) != N_UNDF) continue;
 | 
						|
 | 
						|
	n_sclass = stbl->n_sclass & N_SECT;
 | 
						|
	if (n_sclass == N_ABS)
 | 
						|
		type = 'a';
 | 
						|
	else if (n_sclass == N_TEXT)
 | 
						|
		type = 't';
 | 
						|
	else if (n_sclass == N_DATA)
 | 
						|
		type = 'd';
 | 
						|
	else if (n_sclass == N_BSS)
 | 
						|
		type = 'b';
 | 
						|
	else
 | 
						|
		type = 'u';
 | 
						|
	if ((stbl->n_sclass & N_CLASS) == C_EXT) type += 'A' - 'a';
 | 
						|
	strncpy(name, stbl->n_name, (size_t)8);
 | 
						|
	if (d_flag) {
 | 
						|
		/* Offsets in decimal. */
 | 
						|
		if (o_flag) 
 | 
						|
		       printf("%s:%08ld %c %s\n",file,stbl->n_value,type,name);
 | 
						|
		else
 | 
						|
		       printf("%08ld %c %s\n", stbl->n_value, type, name);
 | 
						|
	} else {
 | 
						|
		/* Offsets in hex. */
 | 
						|
		if (o_flag) 
 | 
						|
		       printf("%s:%08lx %c %s\n",file,stbl->n_value,type,name);
 | 
						|
		else
 | 
						|
		       printf("%08lx %c %s\n", stbl->n_value, type, name);
 | 
						|
	}
 | 
						|
  }
 | 
						|
}
 |