1330449Seadler/*- 2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3330449Seadler * 429042Sjdp * Copyright (C) 1996-1997 John D. Polstra. All rights reserved. 518600Speter * 618600Speter * Redistribution and use in source and binary forms, with or without 718600Speter * modification, are permitted provided that the following conditions 818600Speter * are met: 918600Speter * 1. Redistributions of source code must retain the above copyright 1018600Speter * notice, this list of conditions and the following disclaimer. 1118600Speter * 2. Redistributions in binary form must reproduce the above copyright 1218600Speter * notice, this list of conditions and the following disclaimer in the 1318600Speter * documentation and/or other materials provided with the distribution. 1418600Speter * 1518600Speter * THIS SOFTWARE IS PROVIDED BY JOHN D. POLSTRA AND CONTRIBUTORS ``AS IS'' AND 1618600Speter * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1718600Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1818600Speter * ARE DISCLAIMED. IN NO EVENT SHALL JOHN D. POLSTRA OR CONTRIBUTORS BE LIABLE 1918600Speter * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2018600Speter * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2118600Speter * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2218600Speter * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2318600Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2418600Speter * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2518600Speter * SUCH DAMAGE. 2618600Speter */ 2718600Speter 2895648Smarkm#include <sys/cdefs.h> 2995648Smarkm__FBSDID("$FreeBSD: stable/11/usr.bin/ldd/sods.c 335521 2018-06-22 00:30:24Z emaste $"); 3069827Scharnier 3195648Smarkm#include <sys/types.h> 3295648Smarkm#include <sys/mman.h> 3395648Smarkm#include <sys/stat.h> 3495648Smarkm 3595648Smarkm#include <machine/elf.h> 3695648Smarkm 3795153Smike#include <arpa/inet.h> 3895648Smarkm 3995648Smarkm#include <a.out.h> 4018600Speter#include <assert.h> 4118600Speter#include <ctype.h> 4269827Scharnier#include <err.h> 4318600Speter#include <fcntl.h> 44103436Speter#include <sys/link_aout.h> 4595648Smarkm#include <stab.h> 4618600Speter#include <stdio.h> 4718600Speter#include <stdlib.h> 48125857Sdwmalone#include <string.h> 4918600Speter#include <unistd.h> 5018600Speter 5195648Smarkm#include "extern.h" 5218600Speter 5329042Sjdp#define PAGE_SIZE 4096 /* i386 specific */ 5429042Sjdp 5518600Speter#ifndef N_SETA 5618600Speter#define N_SETA 0x14 /* Absolute set element symbol */ 5718600Speter#endif /* This is input to LD, in a .o file. */ 5818600Speter 5918600Speter#ifndef N_SETT 6018600Speter#define N_SETT 0x16 /* Text set element symbol */ 6118600Speter#endif /* This is input to LD, in a .o file. */ 6218600Speter 6318600Speter#ifndef N_SETD 6418600Speter#define N_SETD 0x18 /* Data set element symbol */ 6518600Speter#endif /* This is input to LD, in a .o file. */ 6618600Speter 6718600Speter#ifndef N_SETB 6818600Speter#define N_SETB 0x1A /* Bss set element symbol */ 6918600Speter#endif /* This is input to LD, in a .o file. */ 7018600Speter 7118600Speter#ifndef N_SETV 7218600Speter#define N_SETV 0x1C /* Pointer to set vector in data area. */ 7318600Speter#endif /* This is output from LD. */ 7418600Speter 7518600Speter#ifdef STANDALONE 7618600Speterstatic 7718600Speter#endif 7818600Speter 7918600Speterstatic void dump_rels(const char *, const struct relocation_info *, 8018600Speter unsigned long, const char *(*)(unsigned long), unsigned char *); 8195648Smarkmstatic void dump_segs(void); 8295648Smarkmstatic void dump_sods(void); 8318600Speterstatic void dump_sym(const struct nlist *); 8495648Smarkmstatic void dump_syms(void); 8518600Speter 8695648Smarkmstatic void dump_rtsyms(void); 8718600Speter 8818600Speterstatic const char *rtsym_name(unsigned long); 8918600Speterstatic const char *sym_name(unsigned long); 9018600Speter 9118600Speter#ifdef STANDALONE 9218600Speterstatic 9318600Speter#endif 9418600Speterint error_count; 9518600Speter 9618600Speter/* 9718600Speter * Variables ending in _base are pointers to things in our address space, 9818600Speter * i.e., in the file itself. 9918600Speter * 10018600Speter * Variables ending in _addr are adjusted according to where things would 10118600Speter * actually appear in memory if the file were loaded. 10218600Speter */ 10318600Speterstatic const char *file_base; 10418600Speterstatic const char *text_base; 10518600Speterstatic const char *data_base; 10618600Speterstatic const struct relocation_info *rel_base; 10718600Speterstatic const struct nlist *sym_base; 10818600Speterstatic const char *str_base; 10918600Speter 11018600Speterstatic const struct relocation_info *rtrel_base; 11118600Speterstatic const struct nzlist *rtsym_base; 11218600Speterstatic const char *rtstr_base; 11318600Speter 11418600Speterstatic const struct exec *ex; 11518600Speterstatic const struct _dynamic *dyn; 11618600Speterstatic const struct section_dispatch_table *sdt; 11718600Speter 11818600Speterstatic const char *text_addr; 11918600Speterstatic const char *data_addr; 12018600Speter 12118600Speterstatic unsigned long rel_count; 12218600Speterstatic unsigned long sym_count; 12318600Speter 12418600Speterstatic unsigned long rtrel_count; 12518600Speterstatic unsigned long rtsym_count; 12618600Speter 12718600Speter/* Dynamically allocated flags, 1 byte per symbol, to record whether each 12818600Speter symbol was referenced by a relocation entry. */ 12918600Speterstatic unsigned char *sym_used; 13018600Speterstatic unsigned char *rtsym_used; 13118600Speter 13218600Speterstatic unsigned long origin; /* What values are relocated relative to */ 13318600Speter 13418600Speter#ifdef STANDALONE 13569827Scharnierint 13618600Spetermain(int argc, char *argv[]) 13718600Speter{ 13818600Speter int i; 13918600Speter 14029042Sjdp for (i = 1; i < argc; ++i) 14118600Speter dump_file(argv[i]); 14218600Speter 14318600Speter return error_count == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 14418600Speter} 14518600Speter#endif 14618600Speter 147223262Sbenlstatic inline const void *align_struct(const void *expr) 148223262Sbenl{ 149223262Sbenl assert(!(((int)expr) & 3)); 150223262Sbenl return expr; 151223262Sbenl} 152223262Sbenl 153223262Sbenlstatic inline const void *align_long(const void *expr) 154223262Sbenl{ 155223262Sbenl assert(!(((int)expr) & 3)); 156223262Sbenl return expr; 157223262Sbenl} 158223262Sbenl 159223262Sbenlstatic inline const void *align_short(const void *expr) 160223262Sbenl{ 161223262Sbenl assert(!(((int)expr) & 1)); 162223262Sbenl return expr; 163223262Sbenl} 164223262Sbenl 16518600Speter#ifdef STANDALONE 16618600Speterstatic 16718600Speter#endif 16818600Spetervoid 16918600Speterdump_file(const char *fname) 17018600Speter{ 17118600Speter int fd; 17218600Speter struct stat sb; 17318600Speter caddr_t objbase; 17418600Speter 17529042Sjdp if (stat(fname, &sb) == -1) { 17669827Scharnier warnx("cannot stat \"%s\"", fname); 17769827Scharnier ++error_count; 17818600Speter return; 17918600Speter } 18018600Speter 18129042Sjdp if ((sb.st_mode & S_IFMT) != S_IFREG) { 18269827Scharnier warnx("\"%s\" is not a regular file", fname); 18369827Scharnier ++error_count; 18418600Speter return; 18518600Speter } 18618600Speter 18729042Sjdp if ((fd = open(fname, O_RDONLY, 0)) == -1) { 18869827Scharnier warnx("cannot open \"%s\"", fname); 18969827Scharnier ++error_count; 19018600Speter return; 19118600Speter } 19218600Speter 19318600Speter objbase = mmap(0, sb.st_size, PROT_READ, MAP_SHARED, fd, 0); 19429042Sjdp if (objbase == (caddr_t) -1) { 19569827Scharnier warnx("cannot mmap \"%s\"", fname); 19669827Scharnier ++error_count; 19718600Speter close(fd); 19818600Speter return; 19918600Speter } 20018600Speter 20118600Speter close(fd); 20218600Speter 20318600Speter file_base = (const char *) objbase; /* Makes address arithmetic easier */ 20418600Speter 205223262Sbenl if (IS_ELF(*(const Elf32_Ehdr*) align_struct(file_base))) { 206335521Semaste warnx("%s: this is an ELF program; use readelf to examine", fname); 20769827Scharnier ++error_count; 20835575Sdfr munmap(objbase, sb.st_size); 20935575Sdfr return; 21035575Sdfr } 21135575Sdfr 212223262Sbenl ex = (const struct exec *) align_struct(file_base); 21318600Speter 214131291Sdwmalone printf("%s: a_midmag = 0x%lx\n", fname, (long)ex->a_midmag); 21529042Sjdp printf(" magic = 0x%lx = 0%lo, netmagic = 0x%lx = 0%lo\n", 216131291Sdwmalone (long)N_GETMAGIC(*ex), (long)N_GETMAGIC(*ex), 21785647Sdillon (long)N_GETMAGIC_NET(*ex), (long)N_GETMAGIC_NET(*ex)); 21818600Speter 21929042Sjdp if (N_BADMAG(*ex)) { 22069827Scharnier warnx("%s: bad magic number", fname); 22169827Scharnier ++error_count; 22218600Speter munmap(objbase, sb.st_size); 22318600Speter return; 22418600Speter } 22518600Speter 226131291Sdwmalone printf(" a_text = 0x%lx\n", (long)ex->a_text); 227131291Sdwmalone printf(" a_data = 0x%lx\n", (long)ex->a_data); 228131291Sdwmalone printf(" a_bss = 0x%lx\n", (long)ex->a_bss); 229131291Sdwmalone printf(" a_syms = 0x%lx\n", (long)ex->a_syms); 230131291Sdwmalone printf(" a_entry = 0x%lx\n", (long)ex->a_entry); 231131291Sdwmalone printf(" a_trsize = 0x%lx\n", (long)ex->a_trsize); 232131291Sdwmalone printf(" a_drsize = 0x%lx\n", (long)ex->a_drsize); 23318600Speter 23418600Speter text_base = file_base + N_TXTOFF(*ex); 23518600Speter data_base = file_base + N_DATOFF(*ex); 236223262Sbenl rel_base = (const struct relocation_info *) 237223262Sbenl align_struct(file_base + N_RELOFF(*ex)); 238223262Sbenl sym_base = (const struct nlist *) align_struct(file_base + N_SYMOFF(*ex)); 23918600Speter str_base = file_base + N_STROFF(*ex); 24018600Speter 24118600Speter rel_count = (ex->a_trsize + ex->a_drsize) / sizeof rel_base[0]; 24218600Speter assert(rel_count * sizeof rel_base[0] == ex->a_trsize + ex->a_drsize); 24318600Speter sym_count = ex->a_syms / sizeof sym_base[0]; 24418600Speter assert(sym_count * sizeof sym_base[0] == ex->a_syms); 24518600Speter 24629042Sjdp if (sym_count != 0) { 24718600Speter sym_used = (unsigned char *) calloc(sym_count, sizeof(unsigned char)); 24818600Speter assert(sym_used != NULL); 24918600Speter } 25018600Speter 251131291Sdwmalone printf(" Entry = 0x%lx\n", (long)ex->a_entry); 25235575Sdfr printf(" Text offset = %x, address = %lx\n", N_TXTOFF(*ex), 253131291Sdwmalone (long)N_TXTADDR(*ex)); 254131291Sdwmalone printf(" Data offset = %lx, address = %lx\n", (long)N_DATOFF(*ex), 255131291Sdwmalone (long)N_DATADDR(*ex)); 25618600Speter 25718600Speter /* 25818600Speter * In an executable program file, everything is relocated relative to 25918600Speter * the assumed run-time load address, i.e., N_TXTADDR(*ex), i.e., 0x1000. 26018600Speter * 26118600Speter * In a shared library file, everything is relocated relative to the 26218600Speter * start of the file, i.e., N_TXTOFF(*ex), i.e., 0. 26318600Speter * 26418600Speter * The way to tell the difference is by looking at ex->a_entry. If it 26518600Speter * is >= 0x1000, then we have an executable program. Otherwise, we 26618600Speter * have a shared library. 26718600Speter * 26818600Speter * When a program is executed, the entire file is mapped into memory, 26918600Speter * including the a.out header and so forth. But it is not mapped at 27018600Speter * address 0; rather it is mapped at address 0x1000. The first page 27118600Speter * of the user's address space is left unmapped in order to catch null 27218600Speter * pointer dereferences. 27318600Speter * 27418600Speter * In this program, when we map in an executable program, we have to 27518600Speter * simulate the empty page by decrementing our assumed base address by 27618600Speter * a pagesize. 27718600Speter */ 27818600Speter 27918600Speter text_addr = text_base; 28018600Speter data_addr = data_base; 28118600Speter origin = 0; 28218600Speter 28329042Sjdp if (ex->a_entry >= PAGE_SIZE) { /* Executable, not a shared library */ 28418600Speter /* 28518600Speter * The fields in the object have already been relocated on the 28618600Speter * assumption that the object will be loaded at N_TXTADDR(*ex). 28718600Speter * We have to compensate for that. 28818600Speter */ 28929042Sjdp text_addr -= PAGE_SIZE; 29029042Sjdp data_addr -= PAGE_SIZE; 29129042Sjdp origin = PAGE_SIZE; 29218600Speter printf(" Program, origin = %lx\n", origin); 29329042Sjdp } else if (N_GETFLAG(*ex) & EX_DYNAMIC) 29429042Sjdp printf(" Shared library, origin = %lx\n", origin); 29529042Sjdp else 29629042Sjdp printf(" Object file, origin = %lx\n", origin); 29718600Speter 29829042Sjdp if (N_GETFLAG(*ex) & EX_DYNAMIC) { 299223262Sbenl dyn = (const struct _dynamic *) align_struct(data_base); 30029042Sjdp printf(" Dynamic version = %d\n", dyn->d_version); 30129042Sjdp 30218600Speter sdt = (const struct section_dispatch_table *) 303223262Sbenl align_struct(text_addr + (unsigned long) dyn->d_un.d_sdt); 30418600Speter 305223262Sbenl rtrel_base = (const struct relocation_info *) 306223262Sbenl align_struct(text_addr + sdt->sdt_rel); 30718600Speter rtrel_count = (sdt->sdt_hash - sdt->sdt_rel) / sizeof rtrel_base[0]; 30818600Speter assert(rtrel_count * sizeof rtrel_base[0] == 309125857Sdwmalone (size_t)(sdt->sdt_hash - sdt->sdt_rel)); 31018600Speter 311223262Sbenl rtsym_base = (const struct nzlist *) 312223262Sbenl align_struct(text_addr + sdt->sdt_nzlist); 31318600Speter rtsym_count = (sdt->sdt_strings - sdt->sdt_nzlist) / 31418600Speter sizeof rtsym_base[0]; 31518600Speter assert(rtsym_count * sizeof rtsym_base[0] == 316125857Sdwmalone (size_t)(sdt->sdt_strings - sdt->sdt_nzlist)); 31718600Speter 31829042Sjdp if (rtsym_count != 0) { 31918600Speter rtsym_used = (unsigned char *) calloc(rtsym_count, 32018600Speter sizeof(unsigned char)); 32118600Speter assert(rtsym_used != NULL); 32218600Speter } 32318600Speter 32418600Speter rtstr_base = text_addr + sdt->sdt_strings; 32518600Speter } 32618600Speter 32718600Speter dump_segs(); 32818600Speter dump_sods(); 32918600Speter dump_rels("Relocations", rel_base, rel_count, sym_name, sym_used); 33018600Speter dump_syms(); 33118600Speter 33218600Speter dump_rels("Run-time relocations", rtrel_base, rtrel_count, rtsym_name, 33318600Speter rtsym_used); 33418600Speter dump_rtsyms(); 33518600Speter 33629042Sjdp if (rtsym_used != NULL) { 33718600Speter free(rtsym_used); 33818600Speter rtsym_used = NULL; 33918600Speter } 34029042Sjdp if (sym_used != NULL) { 34118600Speter free(sym_used); 34218600Speter sym_used = NULL; 34318600Speter } 34418600Speter munmap(objbase, sb.st_size); 34518600Speter} 34618600Speter 34718600Speterstatic void 34818600Speterdump_rels(const char *label, const struct relocation_info *base, 34918600Speter unsigned long count, const char *(*name)(unsigned long), 35018600Speter unsigned char *sym_used_flags) 35118600Speter{ 35218600Speter unsigned long i; 35318600Speter 35418600Speter printf(" %s:\n", label); 35529042Sjdp for (i = 0; i < count; ++i) { 35618600Speter const struct relocation_info *r = &base[i]; 35729042Sjdp unsigned int size; 35829042Sjdp char contents[16]; 35918600Speter 36029042Sjdp size = 1u << r->r_length; 36129042Sjdp 362125857Sdwmalone if (origin <= (unsigned long)r->r_address 363125857Sdwmalone && (unsigned long)r->r_address < origin + ex->a_text + ex->a_data 36429042Sjdp && 1 <= size && size <= 4) { 36529042Sjdp /* 36629042Sjdp * XXX - This can cause unaligned accesses. OK for the 36729042Sjdp * i386, not so for other architectures. 36829042Sjdp */ 36929042Sjdp switch (size) { 37029042Sjdp case 1: 37129042Sjdp snprintf(contents, sizeof contents, " [%02x]", 37295648Smarkm *(unsigned const char *)(text_addr + r->r_address)); 37329042Sjdp break; 37429042Sjdp case 2: 37529042Sjdp snprintf(contents, sizeof contents, " [%04x]", 376223262Sbenl *(unsigned const short *) 377223262Sbenl align_short(text_addr + r->r_address)); 37829042Sjdp break; 37929042Sjdp case 4: 38029042Sjdp snprintf(contents, sizeof contents, "[%08lx]", 381223262Sbenl *(unsigned const long *) 382223262Sbenl align_long(text_addr + r->r_address)); 38329042Sjdp break; 38429042Sjdp } 38529042Sjdp } else 38629042Sjdp snprintf(contents, sizeof contents, " "); 38729042Sjdp 38829042Sjdp printf(" %6lu %8x/%u %s %c%c%c%c%c%c", i, 38929042Sjdp r->r_address, size, 39029042Sjdp contents, 39118600Speter r->r_extern ? 'e' : '-', 39218600Speter r->r_jmptable ? 'j' : '-', 39318600Speter r->r_relative ? 'r' : '-', 39418600Speter r->r_baserel ? 'b' : '-', 39518600Speter r->r_pcrel ? 'p' : '-', 39618600Speter r->r_copy ? 'c' : '-'); 39718600Speter 39829042Sjdp if (r->r_extern || r->r_baserel || r->r_jmptable || r->r_copy) { 39918600Speter printf(" %4u %s", r->r_symbolnum, name(r->r_symbolnum)); 40018600Speter sym_used_flags[r->r_symbolnum] = 1; 40118600Speter } 40218600Speter 40318600Speter printf("\n"); 40418600Speter } 40518600Speter} 40618600Speter 40718600Speterstatic void 40895648Smarkmdump_rtsyms(void) 40918600Speter{ 41018600Speter unsigned long i; 41118600Speter 41218600Speter printf(" Run-time symbols:\n"); 41329042Sjdp for (i = 0; i < rtsym_count; ++i) { 41418600Speter printf(" %6lu%c ", i, rtsym_used[i] ? '*' : ' '); 41518600Speter dump_sym(&rtsym_base[i].nlist); 41618600Speter printf("/%-5ld %s\n", rtsym_base[i].nz_size, rtsym_name(i)); 41718600Speter } 41818600Speter} 41918600Speter 42018600Speterstatic void 42195648Smarkmdump_segs(void) 42218600Speter{ 42318600Speter printf(" Text segment starts at address %lx\n", origin + N_TXTOFF(*ex)); 42429042Sjdp if (N_GETFLAG(*ex) & EX_DYNAMIC) { 42518600Speter printf(" rel starts at %lx\n", sdt->sdt_rel); 42618600Speter printf(" hash starts at %lx\n", sdt->sdt_hash); 42718600Speter printf(" nzlist starts at %lx\n", sdt->sdt_nzlist); 42818600Speter printf(" strings starts at %lx\n", sdt->sdt_strings); 42918600Speter } 43018600Speter 43118600Speter printf(" Data segment starts at address %lx\n", origin + N_DATOFF(*ex)); 43229042Sjdp if (N_GETFLAG(*ex) & EX_DYNAMIC) { 43318600Speter printf(" _dynamic starts at %lx\n", origin + N_DATOFF(*ex)); 43418600Speter printf(" so_debug starts at %lx\n", (unsigned long) dyn->d_debug); 43518600Speter printf(" sdt starts at %lx\n", (unsigned long) dyn->d_un.d_sdt); 43618600Speter printf(" got starts at %lx\n", sdt->sdt_got); 43718600Speter printf(" plt starts at %lx\n", sdt->sdt_plt); 43818600Speter printf(" rest of stuff starts at %lx\n", 43918600Speter sdt->sdt_plt + sdt->sdt_plt_sz); 44018600Speter } 44118600Speter} 44218600Speter 44318600Speterstatic void 44495648Smarkmdump_sods(void) 44518600Speter{ 44618600Speter long sod_offset; 44718600Speter long paths_offset; 44818600Speter 44929042Sjdp if (dyn == NULL) /* Not a shared object */ 45018600Speter return; 45118600Speter 45218600Speter sod_offset = sdt->sdt_sods; 45318600Speter printf(" Shared object dependencies:\n"); 45429042Sjdp while (sod_offset != 0) { 455223262Sbenl const struct sod *sodp = (const struct sod *) align_struct((text_addr + sod_offset)); 45618600Speter const char *name = (const char *) (text_addr + sodp->sod_name); 45718600Speter 45821469Sjdp if (sodp->sod_library) 45921469Sjdp printf(" -l%-16s version %d.%d\n", name, sodp->sod_major, 46021469Sjdp sodp->sod_minor); 46121469Sjdp else 46221469Sjdp printf(" %s\n", name); 46318600Speter sod_offset = sodp->sod_next; 46418600Speter } 46518600Speter paths_offset = sdt->sdt_paths; 46618600Speter printf(" Shared object additional paths:\n"); 46718600Speter if (paths_offset != 0) { 46895648Smarkm printf(" %s\n", (const char *)(text_addr + paths_offset)); 46918600Speter } else { 47029042Sjdp printf(" (none)\n"); 47118600Speter } 47218600Speter} 47318600Speter 47418600Speterstatic void 47518600Speterdump_sym(const struct nlist *np) 47618600Speter{ 47718600Speter char type[8]; 47831442Sjdp char aux[8]; 47929042Sjdp char weak; 48018600Speter char *p; 48118600Speter 48229042Sjdp switch (np->n_type & ~N_EXT) { 48318600Speter case N_UNDF: strcpy(type, "undf"); break; 48418600Speter case N_ABS: strcpy(type, "abs"); break; 48518600Speter case N_TEXT: strcpy(type, "text"); break; 48618600Speter case N_DATA: strcpy(type, "data"); break; 48718600Speter case N_BSS: strcpy(type, "bss"); break; 48818600Speter case N_INDR: strcpy(type, "indr"); break; 48918600Speter case N_SIZE: strcpy(type, "size"); break; 49018600Speter case N_COMM: strcpy(type, "comm"); break; 49118600Speter case N_SETA: strcpy(type, "seta"); break; 49218600Speter case N_SETT: strcpy(type, "sett"); break; 49318600Speter case N_SETD: strcpy(type, "setd"); break; 49418600Speter case N_SETB: strcpy(type, "setb"); break; 49518600Speter case N_SETV: strcpy(type, "setv"); break; 49618600Speter case N_FN: strcpy(type, np->n_type&N_EXT ? "fn" : "warn"); break; 49718600Speter case N_GSYM: strcpy(type, "gsym"); break; 49818600Speter case N_FNAME: strcpy(type, "fname"); break; 49918600Speter case N_FUN: strcpy(type, "fun"); break; 50018600Speter case N_STSYM: strcpy(type, "stsym"); break; 50118600Speter case N_LCSYM: strcpy(type, "lcsym"); break; 50218600Speter case N_MAIN: strcpy(type, "main"); break; 50318600Speter case N_PC: strcpy(type, "pc"); break; 50418600Speter case N_RSYM: strcpy(type, "rsym"); break; 50518600Speter case N_SLINE: strcpy(type, "sline"); break; 50618600Speter case N_DSLINE: strcpy(type, "dsline"); break; 50718600Speter case N_BSLINE: strcpy(type, "bsline"); break; 50818600Speter case N_SSYM: strcpy(type, "ssym"); break; 50918600Speter case N_SO: strcpy(type, "so"); break; 51018600Speter case N_LSYM: strcpy(type, "lsym"); break; 51118600Speter case N_BINCL: strcpy(type, "bincl"); break; 51218600Speter case N_SOL: strcpy(type, "sol"); break; 51318600Speter case N_PSYM: strcpy(type, "psym"); break; 51418600Speter case N_EINCL: strcpy(type, "eincl"); break; 51518600Speter case N_ENTRY: strcpy(type, "entry"); break; 51618600Speter case N_LBRAC: strcpy(type, "lbrac"); break; 51718600Speter case N_EXCL: strcpy(type, "excl"); break; 51818600Speter case N_RBRAC: strcpy(type, "rbrac"); break; 51918600Speter case N_BCOMM: strcpy(type, "bcomm"); break; 52018600Speter case N_ECOMM: strcpy(type, "ecomm"); break; 52118600Speter case N_ECOML: strcpy(type, "ecoml"); break; 52218600Speter case N_LENG: strcpy(type, "leng"); break; 52331442Sjdp default: 52431442Sjdp snprintf(type, sizeof type, "%#02x", np->n_type); 52531442Sjdp break; 52618600Speter } 52718600Speter 52829042Sjdp if (np->n_type & N_EXT && type[0] != '0') 52929042Sjdp for (p = type; *p != '\0'; ++p) 53018600Speter *p = toupper(*p); 53118600Speter 53231442Sjdp switch (N_AUX(np)) { 53331442Sjdp case 0: strcpy(aux, ""); break; 53431442Sjdp case AUX_OBJECT: strcpy(aux, "objt"); break; 53531442Sjdp case AUX_FUNC: strcpy(aux, "func"); break; 53631442Sjdp default: snprintf(aux, sizeof aux, "%#01x", N_AUX(np)); break; 53731442Sjdp } 53831442Sjdp 53929042Sjdp weak = N_BIND(np) == BIND_WEAK ? 'w' : ' '; 54029042Sjdp 54131442Sjdp printf("%c%-6s %-4s %8lx", weak, type, aux, np->n_value); 54218600Speter} 54318600Speter 54418600Speterstatic void 54595648Smarkmdump_syms(void) 54618600Speter{ 54718600Speter unsigned long i; 54818600Speter 54918600Speter printf(" Symbols:\n"); 55029042Sjdp for (i = 0; i < sym_count; ++i) { 55118600Speter printf(" %6lu%c ", i, sym_used[i] ? '*' : ' '); 55218600Speter dump_sym(&sym_base[i]); 55318600Speter printf(" %s\n", sym_name(i)); 55418600Speter } 55518600Speter} 55618600Speter 55718600Speterstatic const char * 55818600Speterrtsym_name(unsigned long n) 55918600Speter{ 56018600Speter assert(n < rtsym_count); 56129042Sjdp if (rtsym_base[n].nz_strx == 0) 56218600Speter return ""; 56318600Speter return rtstr_base + rtsym_base[n].nz_strx; 56418600Speter} 56518600Speter 56618600Speterstatic const char * 56718600Spetersym_name(unsigned long n) 56818600Speter{ 56918600Speter assert(n < sym_count); 57029042Sjdp if (sym_base[n].n_un.n_strx == 0) 57118600Speter return ""; 57218600Speter return str_base + sym_base[n].n_un.n_strx; 57318600Speter} 574