118600Speter/* 229042Sjdp * Copyright (C) 1996-1997 John D. Polstra. All rights reserved. 318600Speter * 418600Speter * Redistribution and use in source and binary forms, with or without 518600Speter * modification, are permitted provided that the following conditions 618600Speter * are met: 718600Speter * 1. Redistributions of source code must retain the above copyright 818600Speter * notice, this list of conditions and the following disclaimer. 918600Speter * 2. Redistributions in binary form must reproduce the above copyright 1018600Speter * notice, this list of conditions and the following disclaimer in the 1118600Speter * documentation and/or other materials provided with the distribution. 1218600Speter * 1318600Speter * THIS SOFTWARE IS PROVIDED BY JOHN D. POLSTRA AND CONTRIBUTORS ``AS IS'' AND 1418600Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1518600Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1618600Speter * ARE DISCLAIMED. IN NO EVENT SHALL JOHN D. POLSTRA OR CONTRIBUTORS BE LIABLE 1718600Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1818600Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1918600Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2018600Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2118600Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2218600Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2318600Speter * SUCH DAMAGE. 2418600Speter */ 2518600Speter 2695648Smarkm#include <sys/cdefs.h> 2795648Smarkm__FBSDID("$FreeBSD$"); 2869827Scharnier 2995648Smarkm#include <sys/types.h> 3095648Smarkm#include <sys/mman.h> 3195648Smarkm#include <sys/stat.h> 3295648Smarkm 3395648Smarkm#include <machine/elf.h> 3495648Smarkm 3595153Smike#include <arpa/inet.h> 3695648Smarkm 3795648Smarkm#include <a.out.h> 3818600Speter#include <assert.h> 3918600Speter#include <ctype.h> 4069827Scharnier#include <err.h> 4118600Speter#include <fcntl.h> 42103436Speter#include <sys/link_aout.h> 4395648Smarkm#include <stab.h> 4418600Speter#include <stdio.h> 4518600Speter#include <stdlib.h> 46125857Sdwmalone#include <string.h> 4718600Speter#include <unistd.h> 4818600Speter 4995648Smarkm#include "extern.h" 5018600Speter 5129042Sjdp#define PAGE_SIZE 4096 /* i386 specific */ 5229042Sjdp 5318600Speter#ifndef N_SETA 5418600Speter#define N_SETA 0x14 /* Absolute set element symbol */ 5518600Speter#endif /* This is input to LD, in a .o file. */ 5618600Speter 5718600Speter#ifndef N_SETT 5818600Speter#define N_SETT 0x16 /* Text set element symbol */ 5918600Speter#endif /* This is input to LD, in a .o file. */ 6018600Speter 6118600Speter#ifndef N_SETD 6218600Speter#define N_SETD 0x18 /* Data set element symbol */ 6318600Speter#endif /* This is input to LD, in a .o file. */ 6418600Speter 6518600Speter#ifndef N_SETB 6618600Speter#define N_SETB 0x1A /* Bss set element symbol */ 6718600Speter#endif /* This is input to LD, in a .o file. */ 6818600Speter 6918600Speter#ifndef N_SETV 7018600Speter#define N_SETV 0x1C /* Pointer to set vector in data area. */ 7118600Speter#endif /* This is output from LD. */ 7218600Speter 7318600Speter#ifdef STANDALONE 7418600Speterstatic 7518600Speter#endif 7618600Speter 7718600Speterstatic void dump_rels(const char *, const struct relocation_info *, 7818600Speter unsigned long, const char *(*)(unsigned long), unsigned char *); 7995648Smarkmstatic void dump_segs(void); 8095648Smarkmstatic void dump_sods(void); 8118600Speterstatic void dump_sym(const struct nlist *); 8295648Smarkmstatic void dump_syms(void); 8318600Speter 8495648Smarkmstatic void dump_rtsyms(void); 8518600Speter 8618600Speterstatic const char *rtsym_name(unsigned long); 8718600Speterstatic const char *sym_name(unsigned long); 8818600Speter 8918600Speter#ifdef STANDALONE 9018600Speterstatic 9118600Speter#endif 9218600Speterint error_count; 9318600Speter 9418600Speter/* 9518600Speter * Variables ending in _base are pointers to things in our address space, 9618600Speter * i.e., in the file itself. 9718600Speter * 9818600Speter * Variables ending in _addr are adjusted according to where things would 9918600Speter * actually appear in memory if the file were loaded. 10018600Speter */ 10118600Speterstatic const char *file_base; 10218600Speterstatic const char *text_base; 10318600Speterstatic const char *data_base; 10418600Speterstatic const struct relocation_info *rel_base; 10518600Speterstatic const struct nlist *sym_base; 10618600Speterstatic const char *str_base; 10718600Speter 10818600Speterstatic const struct relocation_info *rtrel_base; 10918600Speterstatic const struct nzlist *rtsym_base; 11018600Speterstatic const char *rtstr_base; 11118600Speter 11218600Speterstatic const struct exec *ex; 11318600Speterstatic const struct _dynamic *dyn; 11418600Speterstatic const struct section_dispatch_table *sdt; 11518600Speter 11618600Speterstatic const char *text_addr; 11718600Speterstatic const char *data_addr; 11818600Speter 11918600Speterstatic unsigned long rel_count; 12018600Speterstatic unsigned long sym_count; 12118600Speter 12218600Speterstatic unsigned long rtrel_count; 12318600Speterstatic unsigned long rtsym_count; 12418600Speter 12518600Speter/* Dynamically allocated flags, 1 byte per symbol, to record whether each 12618600Speter symbol was referenced by a relocation entry. */ 12718600Speterstatic unsigned char *sym_used; 12818600Speterstatic unsigned char *rtsym_used; 12918600Speter 13018600Speterstatic unsigned long origin; /* What values are relocated relative to */ 13118600Speter 13218600Speter#ifdef STANDALONE 13369827Scharnierint 13418600Spetermain(int argc, char *argv[]) 13518600Speter{ 13618600Speter int i; 13718600Speter 13829042Sjdp for (i = 1; i < argc; ++i) 13918600Speter dump_file(argv[i]); 14018600Speter 14118600Speter return error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 14218600Speter} 14318600Speter#endif 14418600Speter 145223262Sbenlstatic inline const void *align_struct(const void *expr) 146223262Sbenl{ 147223262Sbenl assert(!(((int)expr) & 3)); 148223262Sbenl return expr; 149223262Sbenl} 150223262Sbenl 151223262Sbenlstatic inline const void *align_long(const void *expr) 152223262Sbenl{ 153223262Sbenl assert(!(((int)expr) & 3)); 154223262Sbenl return expr; 155223262Sbenl} 156223262Sbenl 157223262Sbenlstatic inline const void *align_short(const void *expr) 158223262Sbenl{ 159223262Sbenl assert(!(((int)expr) & 1)); 160223262Sbenl return expr; 161223262Sbenl} 162223262Sbenl 16318600Speter#ifdef STANDALONE 16418600Speterstatic 16518600Speter#endif 16618600Spetervoid 16718600Speterdump_file(const char *fname) 16818600Speter{ 16918600Speter int fd; 17018600Speter struct stat sb; 17118600Speter caddr_t objbase; 17218600Speter 17329042Sjdp if (stat(fname, &sb) == -1) { 17469827Scharnier warnx("cannot stat \"%s\"", fname); 17569827Scharnier ++error_count; 17618600Speter return; 17718600Speter } 17818600Speter 17929042Sjdp if ((sb.st_mode & S_IFMT) != S_IFREG) { 18069827Scharnier warnx("\"%s\" is not a regular file", fname); 18169827Scharnier ++error_count; 18218600Speter return; 18318600Speter } 18418600Speter 18529042Sjdp if ((fd = open(fname, O_RDONLY, 0)) == -1) { 18669827Scharnier warnx("cannot open \"%s\"", fname); 18769827Scharnier ++error_count; 18818600Speter return; 18918600Speter } 19018600Speter 19118600Speter objbase = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); 19229042Sjdp if (objbase == (caddr_t) -1) { 19369827Scharnier warnx("cannot mmap \"%s\"", fname); 19469827Scharnier ++error_count; 19518600Speter close(fd); 19618600Speter return; 19718600Speter } 19818600Speter 19918600Speter close(fd); 20018600Speter 20118600Speter file_base = (const char *) objbase; /* Makes address arithmetic easier */ 20218600Speter 203223262Sbenl if (IS_ELF(*(const Elf32_Ehdr*) align_struct(file_base))) { 20469827Scharnier warnx("%s: this is an ELF program; use objdump to examine", fname); 20569827Scharnier ++error_count; 20635575Sdfr munmap(objbase, sb.st_size); 20735575Sdfr return; 20835575Sdfr } 20935575Sdfr 210223262Sbenl ex = (const struct exec *) align_struct(file_base); 21118600Speter 212131291Sdwmalone printf("%s: a_midmag = 0x%lx\n", fname, (long)ex->a_midmag); 21329042Sjdp printf(" magic = 0x%lx = 0%lo, netmagic = 0x%lx = 0%lo\n", 214131291Sdwmalone (long)N_GETMAGIC(*ex), (long)N_GETMAGIC(*ex), 21585647Sdillon (long)N_GETMAGIC_NET(*ex), (long)N_GETMAGIC_NET(*ex)); 21618600Speter 21729042Sjdp if (N_BADMAG(*ex)) { 21869827Scharnier warnx("%s: bad magic number", fname); 21969827Scharnier ++error_count; 22018600Speter munmap(objbase, sb.st_size); 22118600Speter return; 22218600Speter } 22318600Speter 224131291Sdwmalone printf(" a_text = 0x%lx\n", (long)ex->a_text); 225131291Sdwmalone printf(" a_data = 0x%lx\n", (long)ex->a_data); 226131291Sdwmalone printf(" a_bss = 0x%lx\n", (long)ex->a_bss); 227131291Sdwmalone printf(" a_syms = 0x%lx\n", (long)ex->a_syms); 228131291Sdwmalone printf(" a_entry = 0x%lx\n", (long)ex->a_entry); 229131291Sdwmalone printf(" a_trsize = 0x%lx\n", (long)ex->a_trsize); 230131291Sdwmalone printf(" a_drsize = 0x%lx\n", (long)ex->a_drsize); 23118600Speter 23218600Speter text_base = file_base + N_TXTOFF(*ex); 23318600Speter data_base = file_base + N_DATOFF(*ex); 234223262Sbenl rel_base = (const struct relocation_info *) 235223262Sbenl align_struct(file_base + N_RELOFF(*ex)); 236223262Sbenl sym_base = (const struct nlist *) align_struct(file_base + N_SYMOFF(*ex)); 23718600Speter str_base = file_base + N_STROFF(*ex); 23818600Speter 23918600Speter rel_count = (ex->a_trsize + ex->a_drsize) / sizeof rel_base[0]; 24018600Speter assert(rel_count * sizeof rel_base[0] == ex->a_trsize + ex->a_drsize); 24118600Speter sym_count = ex->a_syms / sizeof sym_base[0]; 24218600Speter assert(sym_count * sizeof sym_base[0] == ex->a_syms); 24318600Speter 24429042Sjdp if (sym_count != 0) { 24518600Speter sym_used = (unsigned char *) calloc(sym_count, sizeof(unsigned char)); 24618600Speter assert(sym_used != NULL); 24718600Speter } 24818600Speter 249131291Sdwmalone printf(" Entry = 0x%lx\n", (long)ex->a_entry); 25035575Sdfr printf(" Text offset = %x, address = %lx\n", N_TXTOFF(*ex), 251131291Sdwmalone (long)N_TXTADDR(*ex)); 252131291Sdwmalone printf(" Data offset = %lx, address = %lx\n", (long)N_DATOFF(*ex), 253131291Sdwmalone (long)N_DATADDR(*ex)); 25418600Speter 25518600Speter /* 25618600Speter * In an executable program file, everything is relocated relative to 25718600Speter * the assumed run-time load address, i.e., N_TXTADDR(*ex), i.e., 0x1000. 25818600Speter * 25918600Speter * In a shared library file, everything is relocated relative to the 26018600Speter * start of the file, i.e., N_TXTOFF(*ex), i.e., 0. 26118600Speter * 26218600Speter * The way to tell the difference is by looking at ex->a_entry. If it 26318600Speter * is >= 0x1000, then we have an executable program. Otherwise, we 26418600Speter * have a shared library. 26518600Speter * 26618600Speter * When a program is executed, the entire file is mapped into memory, 26718600Speter * including the a.out header and so forth. But it is not mapped at 26818600Speter * address 0; rather it is mapped at address 0x1000. The first page 26918600Speter * of the user's address space is left unmapped in order to catch null 27018600Speter * pointer dereferences. 27118600Speter * 27218600Speter * In this program, when we map in an executable program, we have to 27318600Speter * simulate the empty page by decrementing our assumed base address by 27418600Speter * a pagesize. 27518600Speter */ 27618600Speter 27718600Speter text_addr = text_base; 27818600Speter data_addr = data_base; 27918600Speter origin = 0; 28018600Speter 28129042Sjdp if (ex->a_entry >= PAGE_SIZE) { /* Executable, not a shared library */ 28218600Speter /* 28318600Speter * The fields in the object have already been relocated on the 28418600Speter * assumption that the object will be loaded at N_TXTADDR(*ex). 28518600Speter * We have to compensate for that. 28618600Speter */ 28729042Sjdp text_addr -= PAGE_SIZE; 28829042Sjdp data_addr -= PAGE_SIZE; 28929042Sjdp origin = PAGE_SIZE; 29018600Speter printf(" Program, origin = %lx\n", origin); 29129042Sjdp } else if (N_GETFLAG(*ex) & EX_DYNAMIC) 29229042Sjdp printf(" Shared library, origin = %lx\n", origin); 29329042Sjdp else 29429042Sjdp printf(" Object file, origin = %lx\n", origin); 29518600Speter 29629042Sjdp if (N_GETFLAG(*ex) & EX_DYNAMIC) { 297223262Sbenl dyn = (const struct _dynamic *) align_struct(data_base); 29829042Sjdp printf(" Dynamic version = %d\n", dyn->d_version); 29929042Sjdp 30018600Speter sdt = (const struct section_dispatch_table *) 301223262Sbenl align_struct(text_addr + (unsigned long) dyn->d_un.d_sdt); 30218600Speter 303223262Sbenl rtrel_base = (const struct relocation_info *) 304223262Sbenl align_struct(text_addr + sdt->sdt_rel); 30518600Speter rtrel_count = (sdt->sdt_hash - sdt->sdt_rel) / sizeof rtrel_base[0]; 30618600Speter assert(rtrel_count * sizeof rtrel_base[0] == 307125857Sdwmalone (size_t)(sdt->sdt_hash - sdt->sdt_rel)); 30818600Speter 309223262Sbenl rtsym_base = (const struct nzlist *) 310223262Sbenl align_struct(text_addr + sdt->sdt_nzlist); 31118600Speter rtsym_count = (sdt->sdt_strings - sdt->sdt_nzlist) / 31218600Speter sizeof rtsym_base[0]; 31318600Speter assert(rtsym_count * sizeof rtsym_base[0] == 314125857Sdwmalone (size_t)(sdt->sdt_strings - sdt->sdt_nzlist)); 31518600Speter 31629042Sjdp if (rtsym_count != 0) { 31718600Speter rtsym_used = (unsigned char *) calloc(rtsym_count, 31818600Speter sizeof(unsigned char)); 31918600Speter assert(rtsym_used != NULL); 32018600Speter } 32118600Speter 32218600Speter rtstr_base = text_addr + sdt->sdt_strings; 32318600Speter } 32418600Speter 32518600Speter dump_segs(); 32618600Speter dump_sods(); 32718600Speter dump_rels("Relocations", rel_base, rel_count, sym_name, sym_used); 32818600Speter dump_syms(); 32918600Speter 33018600Speter dump_rels("Run-time relocations", rtrel_base, rtrel_count, rtsym_name, 33118600Speter rtsym_used); 33218600Speter dump_rtsyms(); 33318600Speter 33429042Sjdp if (rtsym_used != NULL) { 33518600Speter free(rtsym_used); 33618600Speter rtsym_used = NULL; 33718600Speter } 33829042Sjdp if (sym_used != NULL) { 33918600Speter free(sym_used); 34018600Speter sym_used = NULL; 34118600Speter } 34218600Speter munmap(objbase, sb.st_size); 34318600Speter} 34418600Speter 34518600Speterstatic void 34618600Speterdump_rels(const char *label, const struct relocation_info *base, 34718600Speter unsigned long count, const char *(*name)(unsigned long), 34818600Speter unsigned char *sym_used_flags) 34918600Speter{ 35018600Speter unsigned long i; 35118600Speter 35218600Speter printf(" %s:\n", label); 35329042Sjdp for (i = 0; i < count; ++i) { 35418600Speter const struct relocation_info *r = &base[i]; 35529042Sjdp unsigned int size; 35629042Sjdp char contents[16]; 35718600Speter 35829042Sjdp size = 1u << r->r_length; 35929042Sjdp 360125857Sdwmalone if (origin <= (unsigned long)r->r_address 361125857Sdwmalone && (unsigned long)r->r_address < origin + ex->a_text + ex->a_data 36229042Sjdp && 1 <= size && size <= 4) { 36329042Sjdp /* 36429042Sjdp * XXX - This can cause unaligned accesses. OK for the 36529042Sjdp * i386, not so for other architectures. 36629042Sjdp */ 36729042Sjdp switch (size) { 36829042Sjdp case 1: 36929042Sjdp snprintf(contents, sizeof contents, " [%02x]", 37095648Smarkm *(unsigned const char *)(text_addr + r->r_address)); 37129042Sjdp break; 37229042Sjdp case 2: 37329042Sjdp snprintf(contents, sizeof contents, " [%04x]", 374223262Sbenl *(unsigned const short *) 375223262Sbenl align_short(text_addr + r->r_address)); 37629042Sjdp break; 37729042Sjdp case 4: 37829042Sjdp snprintf(contents, sizeof contents, "[%08lx]", 379223262Sbenl *(unsigned const long *) 380223262Sbenl align_long(text_addr + r->r_address)); 38129042Sjdp break; 38229042Sjdp } 38329042Sjdp } else 38429042Sjdp snprintf(contents, sizeof contents, " "); 38529042Sjdp 38629042Sjdp printf(" %6lu %8x/%u %s %c%c%c%c%c%c", i, 38729042Sjdp r->r_address, size, 38829042Sjdp contents, 38918600Speter r->r_extern ? 'e' : '-', 39018600Speter r->r_jmptable ? 'j' : '-', 39118600Speter r->r_relative ? 'r' : '-', 39218600Speter r->r_baserel ? 'b' : '-', 39318600Speter r->r_pcrel ? 'p' : '-', 39418600Speter r->r_copy ? 'c' : '-'); 39518600Speter 39629042Sjdp if (r->r_extern || r->r_baserel || r->r_jmptable || r->r_copy) { 39718600Speter printf(" %4u %s", r->r_symbolnum, name(r->r_symbolnum)); 39818600Speter sym_used_flags[r->r_symbolnum] = 1; 39918600Speter } 40018600Speter 40118600Speter printf("\n"); 40218600Speter } 40318600Speter} 40418600Speter 40518600Speterstatic void 40695648Smarkmdump_rtsyms(void) 40718600Speter{ 40818600Speter unsigned long i; 40918600Speter 41018600Speter printf(" Run-time symbols:\n"); 41129042Sjdp for (i = 0; i < rtsym_count; ++i) { 41218600Speter printf(" %6lu%c ", i, rtsym_used[i] ? '*' : ' '); 41318600Speter dump_sym(&rtsym_base[i].nlist); 41418600Speter printf("/%-5ld %s\n", rtsym_base[i].nz_size, rtsym_name(i)); 41518600Speter } 41618600Speter} 41718600Speter 41818600Speterstatic void 41995648Smarkmdump_segs(void) 42018600Speter{ 42118600Speter printf(" Text segment starts at address %lx\n", origin + N_TXTOFF(*ex)); 42229042Sjdp if (N_GETFLAG(*ex) & EX_DYNAMIC) { 42318600Speter printf(" rel starts at %lx\n", sdt->sdt_rel); 42418600Speter printf(" hash starts at %lx\n", sdt->sdt_hash); 42518600Speter printf(" nzlist starts at %lx\n", sdt->sdt_nzlist); 42618600Speter printf(" strings starts at %lx\n", sdt->sdt_strings); 42718600Speter } 42818600Speter 42918600Speter printf(" Data segment starts at address %lx\n", origin + N_DATOFF(*ex)); 43029042Sjdp if (N_GETFLAG(*ex) & EX_DYNAMIC) { 43118600Speter printf(" _dynamic starts at %lx\n", origin + N_DATOFF(*ex)); 43218600Speter printf(" so_debug starts at %lx\n", (unsigned long) dyn->d_debug); 43318600Speter printf(" sdt starts at %lx\n", (unsigned long) dyn->d_un.d_sdt); 43418600Speter printf(" got starts at %lx\n", sdt->sdt_got); 43518600Speter printf(" plt starts at %lx\n", sdt->sdt_plt); 43618600Speter printf(" rest of stuff starts at %lx\n", 43718600Speter sdt->sdt_plt + sdt->sdt_plt_sz); 43818600Speter } 43918600Speter} 44018600Speter 44118600Speterstatic void 44295648Smarkmdump_sods(void) 44318600Speter{ 44418600Speter long sod_offset; 44518600Speter long paths_offset; 44618600Speter 44729042Sjdp if (dyn == NULL) /* Not a shared object */ 44818600Speter return; 44918600Speter 45018600Speter sod_offset = sdt->sdt_sods; 45118600Speter printf(" Shared object dependencies:\n"); 45229042Sjdp while (sod_offset != 0) { 453223262Sbenl const struct sod *sodp = (const struct sod *) align_struct((text_addr + sod_offset)); 45418600Speter const char *name = (const char *) (text_addr + sodp->sod_name); 45518600Speter 45621469Sjdp if (sodp->sod_library) 45721469Sjdp printf(" -l%-16s version %d.%d\n", name, sodp->sod_major, 45821469Sjdp sodp->sod_minor); 45921469Sjdp else 46021469Sjdp printf(" %s\n", name); 46118600Speter sod_offset = sodp->sod_next; 46218600Speter } 46318600Speter paths_offset = sdt->sdt_paths; 46418600Speter printf(" Shared object additional paths:\n"); 46518600Speter if (paths_offset != 0) { 46695648Smarkm printf(" %s\n", (const char *)(text_addr + paths_offset)); 46718600Speter } else { 46829042Sjdp printf(" (none)\n"); 46918600Speter } 47018600Speter} 47118600Speter 47218600Speterstatic void 47318600Speterdump_sym(const struct nlist *np) 47418600Speter{ 47518600Speter char type[8]; 47631442Sjdp char aux[8]; 47729042Sjdp char weak; 47818600Speter char *p; 47918600Speter 48029042Sjdp switch (np->n_type & ~N_EXT) { 48118600Speter case N_UNDF: strcpy(type, "undf"); break; 48218600Speter case N_ABS: strcpy(type, "abs"); break; 48318600Speter case N_TEXT: strcpy(type, "text"); break; 48418600Speter case N_DATA: strcpy(type, "data"); break; 48518600Speter case N_BSS: strcpy(type, "bss"); break; 48618600Speter case N_INDR: strcpy(type, "indr"); break; 48718600Speter case N_SIZE: strcpy(type, "size"); break; 48818600Speter case N_COMM: strcpy(type, "comm"); break; 48918600Speter case N_SETA: strcpy(type, "seta"); break; 49018600Speter case N_SETT: strcpy(type, "sett"); break; 49118600Speter case N_SETD: strcpy(type, "setd"); break; 49218600Speter case N_SETB: strcpy(type, "setb"); break; 49318600Speter case N_SETV: strcpy(type, "setv"); break; 49418600Speter case N_FN: strcpy(type, np->n_type&N_EXT ? "fn" : "warn"); break; 49518600Speter case N_GSYM: strcpy(type, "gsym"); break; 49618600Speter case N_FNAME: strcpy(type, "fname"); break; 49718600Speter case N_FUN: strcpy(type, "fun"); break; 49818600Speter case N_STSYM: strcpy(type, "stsym"); break; 49918600Speter case N_LCSYM: strcpy(type, "lcsym"); break; 50018600Speter case N_MAIN: strcpy(type, "main"); break; 50118600Speter case N_PC: strcpy(type, "pc"); break; 50218600Speter case N_RSYM: strcpy(type, "rsym"); break; 50318600Speter case N_SLINE: strcpy(type, "sline"); break; 50418600Speter case N_DSLINE: strcpy(type, "dsline"); break; 50518600Speter case N_BSLINE: strcpy(type, "bsline"); break; 50618600Speter case N_SSYM: strcpy(type, "ssym"); break; 50718600Speter case N_SO: strcpy(type, "so"); break; 50818600Speter case N_LSYM: strcpy(type, "lsym"); break; 50918600Speter case N_BINCL: strcpy(type, "bincl"); break; 51018600Speter case N_SOL: strcpy(type, "sol"); break; 51118600Speter case N_PSYM: strcpy(type, "psym"); break; 51218600Speter case N_EINCL: strcpy(type, "eincl"); break; 51318600Speter case N_ENTRY: strcpy(type, "entry"); break; 51418600Speter case N_LBRAC: strcpy(type, "lbrac"); break; 51518600Speter case N_EXCL: strcpy(type, "excl"); break; 51618600Speter case N_RBRAC: strcpy(type, "rbrac"); break; 51718600Speter case N_BCOMM: strcpy(type, "bcomm"); break; 51818600Speter case N_ECOMM: strcpy(type, "ecomm"); break; 51918600Speter case N_ECOML: strcpy(type, "ecoml"); break; 52018600Speter case N_LENG: strcpy(type, "leng"); break; 52131442Sjdp default: 52231442Sjdp snprintf(type, sizeof type, "%#02x", np->n_type); 52331442Sjdp break; 52418600Speter } 52518600Speter 52629042Sjdp if (np->n_type & N_EXT && type[0] != '0') 52729042Sjdp for (p = type; *p != '\0'; ++p) 52818600Speter *p = toupper(*p); 52918600Speter 53031442Sjdp switch (N_AUX(np)) { 53131442Sjdp case 0: strcpy(aux, ""); break; 53231442Sjdp case AUX_OBJECT: strcpy(aux, "objt"); break; 53331442Sjdp case AUX_FUNC: strcpy(aux, "func"); break; 53431442Sjdp default: snprintf(aux, sizeof aux, "%#01x", N_AUX(np)); break; 53531442Sjdp } 53631442Sjdp 53729042Sjdp weak = N_BIND(np) == BIND_WEAK ? 'w' : ' '; 53829042Sjdp 53931442Sjdp printf("%c%-6s %-4s %8lx", weak, type, aux, np->n_value); 54018600Speter} 54118600Speter 54218600Speterstatic void 54395648Smarkmdump_syms(void) 54418600Speter{ 54518600Speter unsigned long i; 54618600Speter 54718600Speter printf(" Symbols:\n"); 54829042Sjdp for (i = 0; i < sym_count; ++i) { 54918600Speter printf(" %6lu%c ", i, sym_used[i] ? '*' : ' '); 55018600Speter dump_sym(&sym_base[i]); 55118600Speter printf(" %s\n", sym_name(i)); 55218600Speter } 55318600Speter} 55418600Speter 55518600Speterstatic const char * 55618600Speterrtsym_name(unsigned long n) 55718600Speter{ 55818600Speter assert(n < rtsym_count); 55929042Sjdp if (rtsym_base[n].nz_strx == 0) 56018600Speter return ""; 56118600Speter return rtstr_base + rtsym_base[n].nz_strx; 56218600Speter} 56318600Speter 56418600Speterstatic const char * 56518600Spetersym_name(unsigned long n) 56618600Speter{ 56718600Speter assert(n < sym_count); 56829042Sjdp if (sym_base[n].n_un.n_strx == 0) 56918600Speter return ""; 57018600Speter return str_base + sym_base[n].n_un.n_strx; 57118600Speter} 572