scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | LICENSE

elf.c (20676B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #include <scc/mach.h>
      6 #include <scc/elf/elftypes.h>
      7 #include <scc/elf/elfhdr.h>
      8 #include <scc/elf/elfphdr.h>
      9 #include <scc/elf/elfshdr.h>
     10 #include <scc/elf/elfent.h>
     11 #include <scc/elf.h>
     12 
     13 #include "objdump.h"
     14 
     15 enum elfsecflags {
     16 	ELF_WRITE = 0,
     17 	ELF_ALLOC = 1,
     18 	ELF_EXEC = 2,
     19 	ELF_MERGE = 3,
     20 	ELF_STRINGS = 4,
     21 	ELF_INFO_LINK = 5,
     22 	ELF_LINK_ORDER = 6,
     23 	ELF_OS_NONCONFOR = 7,
     24 	ELF_GROUP = 8,
     25 	ELF_TLS = 9,
     26 	ELF_COMPRESSED = 10,
     27 	ELF_NR_FLAGS = 11,
     28 };
     29 
     30 enum phdrflags {
     31 	FLAG_X = 0,
     32 	FLAG_W = 1,
     33 	FLAG_R = 2,
     34 	NR_RIGHTS = 3,
     35 };
     36 
     37 int
     38 elfhasrelloc(Obj *obj, Section *sec)
     39 {
     40 	size_t i;
     41 	Elf *elf = obj->data;
     42 	Elfsec *shdr;
     43 
     44 	for (i = 0; i < elf->nsec; i++) {
     45 		shdr = &elf->secs[i];
     46 		if (shdr->type != SHT_RELA && shdr->type != SHT_REL)
     47 			continue;
     48 		if (shdr->info == sec->index)
     49 			return 1;
     50 	}
     51 
     52 	return 0;
     53 }
     54 
     55 static void
     56 printents(Obj *obj)
     57 {
     58 	int n;
     59 	size_t i;
     60 	Section sec;
     61 	Elfsym *ent;
     62 	Elf *elf = obj->data;
     63 	char *sbind, *stype, *svis, *ssec;
     64 	unsigned info, bind, type, vis, nsec;
     65 
     66 	static char *binds[] = {
     67 		[STB_LOCAL] = "Local symbol",
     68 		[STB_GLOBAL] = "Global symbol",
     69 		[STB_WEAK] = "like global - lower precedence",
     70 		[STB_NUM] = "number of symbol bindings",
     71 		[STB_LOPROC] = "reserved range for processor",
     72 		[STB_HIPROC] = " specific symbol bindings",
     73 	};
     74 	static char *types[] = {
     75 		[STT_NOTYPE] = "not specified",
     76 		[STT_OBJECT] = "data object",
     77 		[STT_FUNC] = "function",
     78 		[STT_SECTION] = "section",
     79 		[STT_FILE] = "file",
     80 		[STT_COMMON] = "common symbol",
     81 		[STT_TLS] = "thread local storage",
     82 		[STT_LOPROC] = "reserved range for processor",
     83 		[STT_HIPROC] = " specific symbol types",
     84 	};
     85 	static char *visibilities[] = {
     86 		[STV_DEFAULT] = "Visibility set by binding type",
     87 		[STV_INTERNAL] = "OS specific version of STV_HIDDEN",
     88 		[STV_HIDDEN] = "can only be seen inside own .so",
     89 		[STV_PROTECTED] = "HIDDEN inside, DEFAULT outside",
     90 	};
     91 
     92 	for (i = 0; i < elf->nsym; i++) {
     93 		ent = &elf->syms[i];
     94 
     95 		info = ent->info;
     96 		bind = ELF_ST_BIND(info);
     97 		type = ELF_ST_TYPE(info);
     98 		vis = ELF_ST_VISIBILITY(ent->other);
     99 		nsec = ent->shndx;
    100 
    101 		sbind = (bind <= STB_HIPROC) ? binds[bind] : "Unknown";
    102 		stype = (type <= STT_HIPROC) ? types[type] : "Unknown";
    103 		svis = (vis <= STV_PROTECTED) ? visibilities[vis] : "Unknown";
    104 		if (!sbind)
    105 			sbind = "Unknown";
    106 		if (!stype)
    107 			stype = "Unknown";
    108 		if (!svis)
    109 			svis = "Unknown";
    110 
    111 		switch (nsec) {
    112 		case SHN_ABS:
    113 			ssec = "*ABS*";
    114 			break;
    115 		case SHN_COMMON:
    116 			ssec = "*COM*";
    117 			break;
    118 		default:
    119 			n = nsec;
    120 			ssec = "*UNK*";
    121 			if (getsec(obj, &n, &sec))
    122 				ssec = sec.name;
    123 		}
    124 
    125 		printf("Symbol %zu:\n"
    126 		        "\tst_name: %lu '%s'\n"
    127 		        "\tst_info: %u\n"
    128 		        "\t\tst_bind: %u %s\n"
    129 		        "\t\tst_type: %u %s\n"
    130 		        "\tst_other: %u %s\n"
    131 		        "\tst_shndx: %u %s\n"
    132 		        "\tst_value: %#llx\n"
    133 		        "\tst_size: %llu\n"
    134 		        "\n",
    135 		        i,
    136 		        (long) ent->st_name, ent->name,
    137 		        info,
    138 		        bind, sbind,
    139 		        type, stype,
    140 		        vis, svis,
    141 		        nsec, ssec,
    142 		        (unsigned long long) ent->value,
    143 		        (unsigned long long) ent->size);
    144 	}
    145 }
    146 
    147 static void
    148 printstbl(Obj *obj)
    149 {
    150 	int n;
    151 	size_t i;
    152 	Symbol sym;
    153 	Section sec;
    154 	Elfsym *ent;
    155 	Elfsec *shdr;
    156 	Elf *elf = obj->data;
    157 	unsigned info, bind, type;
    158 	char cbind, cweak, cctor, cwarn, cindir, cdebug, ctype;
    159 
    160 	if (elf->nsym == 0) {
    161 		puts("no symbols");
    162 		return;
    163 	}
    164 
    165 	for (i = 1; i < elf->nsym; i++) {
    166 		ent = &elf->syms[i];
    167 		shdr =&elf->secs[ent->shndx];
    168 		n = i;
    169 		getsym(obj, &n, &sym);
    170 		n = ent->shndx;
    171 		getsec(obj, &n, &sec);
    172 
    173 		info = ent->info;
    174 		bind = ELF64_ST_BIND(info);
    175 		type = ELF64_ST_TYPE(info);
    176 
    177 		cbind = (bind == STB_LOCAL) ? 'l' : 'g';
    178 		cweak = (bind == STB_WEAK) ? 'w' : ' ';
    179 		cctor = ' ';
    180 		cwarn = ' ';
    181 		cindir = ' ';
    182 
    183 		switch (sym.type) {
    184 		case 'N':
    185 		case 'n':
    186 			cdebug = 'd';
    187 			break;
    188 		case 'U':
    189 			cdebug = ' ';
    190 			cbind = ' ';
    191 			break;
    192 		default:
    193 			cdebug = (ent->symsec->type  == SHT_DYNAMIC) ? 'D' : ' ';
    194 		}
    195 
    196 		switch (type) {
    197 		case STT_OBJECT:
    198 			ctype = 'O';
    199 			break;
    200 		case STT_FUNC:
    201 			ctype = 'F';
    202 			break;
    203 		case STT_FILE:
    204 			ctype = 'f';
    205 			cdebug = 'd';
    206 			break;
    207 		default:
    208 			ctype = ' ';
    209 			break;
    210 		}
    211 
    212 		printf("%016llx %c%c%c%c%c%c%c %-15s %08llu %-20s [%4zu]\n",
    213 		       (long long) ent->value,
    214 		       cbind,
    215 		       cweak,
    216 		       cctor,
    217 		       cwarn,
    218 		       cindir,
    219 		       cdebug,
    220 		       ctype,
    221 		       sec.name,
    222 		       (long long) ent->size,
    223 		       sym.name,
    224 		       i);
    225 	}
    226 }
    227 
    228 void
    229 elfsyms(Obj *obj)
    230 {
    231 	printstbl(obj);
    232 
    233 	if (pflag)
    234 		printents(obj);
    235 }
    236 
    237 void
    238 elfscns(Obj *obj)
    239 {
    240 	size_t i;
    241 	Elf *elf = obj->data;
    242 	Elfsec *shdr;
    243 	static char *types[] = {
    244 		[SHT_NULL] = "inactive",
    245 		[SHT_PROGBITS] = "program defined information",
    246 		[SHT_SYMTAB] = "symbol table section",
    247 		[SHT_STRTAB] = "string table section",
    248 		[SHT_RELA] = "relocation section with addends",
    249 		[SHT_HASH] = "symbol hash table section",
    250 		[SHT_DYNAMIC] = "dynamic section",
    251 		[SHT_NOTE] = "note section",
    252 		[SHT_NOBITS] = "no space section",
    253 		[SHT_REL] = "relation section without addends",
    254 		[SHT_SHLIB] = "reserved - purpose unknown",
    255 		[SHT_DYNSYM] = "dynamic symbol table section",
    256 		[SHT_NUM] = "number of section types",
    257 		[SHT_INIT_ARRAY] = "pointers to init functions",
    258 		[SHT_FINI_ARRAY] = "pointers to termination functions",
    259 		[SHT_PREINIT_ARRAY] = "ptrs to funcs called before init",
    260 		[SHT_GROUP] = "defines a section group",
    261 		[SHT_SYMTAB_SHNDX] = "Section indexes (see SHN_XINDEX).",
    262 	};
    263 	static Flags f = {
    264 		.nr = ELF_NR_FLAGS,
    265 		.text = {
    266 			[ELF_WRITE] = "WRITE",
    267 			[ELF_ALLOC] = "ALLOC",
    268 			[ELF_EXEC] = "EXEC",
    269 			[ELF_MERGE] = "MERGE",
    270 			[ELF_STRINGS] = "STRINGS",
    271 			[ELF_INFO_LINK] = "INFO_LINK",
    272 			[ELF_LINK_ORDER] = "LINK_ORDER",
    273 			[ELF_OS_NONCONFOR] = "OS_NONCONFORMING",
    274 			[ELF_GROUP] = "GROUP",
    275 			[ELF_TLS] = "TLS",
    276 			[ELF_COMPRESSED] = "COMPRESSED",
    277 		}
    278 	};
    279 
    280 	for (i = 0; i < elf->nsec; i++) {
    281 		long type;
    282 		char *stype;
    283 		shdr = &elf->secs[i];
    284 
    285 		type = shdr->type;
    286 		if (type <= SHT_SYMTAB_SHNDX) {
    287 			stype = types[type];
    288 		} else {
    289 			switch (type) {
    290 			case SHT_SUNW_dof:
    291 				stype = "SHT_SUNW_dof";
    292 				break;
    293 			case SHT_GNU_LIBLIST:
    294 				stype = "SHT_GNU_LIBLIST";
    295 				break;
    296 			case SHT_SUNW_move:
    297 				stype = "SHT_SUNW_move";
    298 				break;
    299 			case SHT_SUNW_syminfo:
    300 				stype = "SHT_SUNW_syminfo";
    301 				break;
    302 			case SHT_GNU_VERDEF:
    303 				stype = "SHT_GNU_VERDEF";
    304 				break;
    305 			case SHT_GNU_VERNEED:
    306 				stype = "SHT_GNU_VERNEED";
    307 				break;
    308 			case SHT_GNU_VERSYM:
    309 				stype = "SHT_GNU_VERSYM";
    310 				break;
    311 			default:
    312 				stype = NULL;
    313 			}
    314 		}
    315 
    316 		if (!stype)
    317 			stype = "Unknown";
    318 
    319 		f.flags = shdr->flags;
    320 
    321 		printf("Section %zu:\n"
    322 		       "\tsh_name: %lu %s\n"
    323 		       "\tsh_type: %lu %s\n"
    324 		       "\tsh_flags: %#llx\n"
    325 		       "\tsh_addr: %#llx\n"
    326 		       "\tsh_offset: %#llx\n"
    327 		       "\tsh_size: %#llx\n"
    328 		       "\tsh_link: %lu\n"
    329 		       "\tsh_info: %lu\n"
    330 		       "\tsh_addralign: %llu\n"
    331 		       "\tsh_entsize: %llu\n",
    332 		       i,
    333 		       (long) shdr->sh_name, shdr->name,
    334 		       type, stype,
    335 		       (long long) shdr->flags,
    336 		       (long long) shdr->addr,
    337 		       (long long) shdr->offset,
    338 		       (long long) shdr->size,
    339 		       (long) shdr->link,
    340 		       (long) shdr->info,
    341 		       (long long) shdr->addralign,
    342 		       (long long) shdr->entsize);
    343 
    344 		putchar('\t');
    345 		printflags(&f);
    346 		putchar('\n');
    347 	}
    348 }
    349 
    350 static void
    351 printfhdr(Elfhdr *hdr)
    352 {
    353 	unsigned long version;
    354 	unsigned class, data, abi, type, mach;
    355 	char *sclass, *sdata, *sabi, *stype, *smach, *sversion;
    356 
    357 	static char *abis[] = {
    358 		[ELFOSABI_SYSV] = "UNIX System V ABI",
    359 		[ELFOSABI_HPUX] = "HP-UX operating system",
    360 		[ELFOSABI_NETBSD] = "NetBSD",
    361 		[ELFOSABI_LINUX] = "GNU/Linux",
    362 		[ELFOSABI_HURD] = "GNU/Hurd",
    363 		[ELFOSABI_86OPEN] = "86Open common IA32 ABI",
    364 		[ELFOSABI_SOLARIS] = "Solaris",
    365 		[ELFOSABI_MONTEREY] = "Monterey",
    366 		[ELFOSABI_IRIX] = "IRIX",
    367 		[ELFOSABI_FREEBSD] = "FreeBSD",
    368 		[ELFOSABI_TRU64] = "TRU64 UNIX",
    369 		[ELFOSABI_MODESTO] = "Novell Modesto",
    370 		[ELFOSABI_OPENBSD] = "OpenBSD",
    371 		[ELFOSABI_OPENVMS] = "Open VMS",
    372 		[ELFOSABI_NSK] = "Hewlett-Packard Non-Stop Kernel",
    373 		[ELFOSABI_AROS] = "Amiga Research OS",
    374 		[ELFOSABI_FENIXOS] = "The FenixOS multi-core OS",
    375 		[ELFOSABI_CLOUDABI] = "Nuxi CloudABI",
    376 		[ELFOSABI_OPENVOS] = "Stratus Technologies OpenVOS",
    377 		[ELFOSABI_ARM] = "ARM",
    378 		[ELFOSABI_STANDALONE] = "Standalone (embedded) application",
    379 	};
    380 	static char *classes[] = {
    381 		[ELFCLASSNONE] = "invalid",
    382 		[ELFCLASS32] = "32-bit objs",
    383 		[ELFCLASS64] = "64-bit objs",
    384 	};
    385 	static char *datas[] = {
    386 		[ELFDATANONE] = "invalid",
    387 		[ELFDATA2LSB] = "Little-Endian",
    388 		[ELFDATA2MSB] = "Big-Endian",
    389 	};
    390 	static char *types[] = {
    391 		[ET_NONE] = "No file type",
    392 		[ET_REL] = "Relocatable file",
    393 		[ET_EXEC] = "Executable file",
    394 		[ET_DYN] = "Shared object file",
    395 		[ET_CORE] = "Core file",
    396 	};
    397 	static char *machs[] = {
    398 		[EM_NONE] = "No machine",
    399 		[EM_M32] = "AT&T WE 32100",
    400 		[EM_SPARC] = "SPARC",
    401 		[EM_386] = "Intel 80386",
    402 		[EM_68K] = "Motorola 68000",
    403 		[EM_88K] = "Motorola 88000",
    404 		[EM_IAMCU] = "Intel MCU",
    405 		[EM_860] = "Intel 80860",
    406 		[EM_MIPS] = "MIPS I Architecture",
    407 		[EM_S370] = "IBM System/370 Processor",
    408 		[EM_MIPS_RS3_LE] = "MIPS RS3000 Little-endian",
    409 		[EM_PARISC] = "Hewlett-Packard PA-RISC",
    410 		[EM_VPP500] = "Fujitsu VPP500",
    411 		[EM_SPARC32PLUS] = "Enhanced instruction set SPARC",
    412 		[EM_960] = "Intel 80960",
    413 		[EM_PPC] = "PowerPC",
    414 		[EM_PPC64] = "64-bit PowerPC",
    415 		[EM_S390] = "IBM System/390",
    416 		[EM_SPU] = "IBM SPU/SPC",
    417 		[EM_V800] = "NEC V800",
    418 		[EM_FR20] = "Fujitsu FR20",
    419 		[EM_RH32] = "TRW RH-32",
    420 		[EM_RCE] = "Motorola RCE",
    421 		[EM_ARM] = "ARM AARCH32",
    422 		[EM_ALPHA] = "Digital Alpha",
    423 		[EM_SH] = "Hitachi SH",
    424 		[EM_SPARCV9] = "SPARC Version 9",
    425 		[EM_TRICORE] = "Siemens TriCore",
    426 		[EM_ARC] = "Argonaut RISC Core",
    427 		[EM_H8_300] = "Hitachi H8/300",
    428 		[EM_H8_300H] = "Hitachi H8/300H",
    429 		[EM_H8S] = "Hitachi H8S",
    430 		[EM_H8_500] = "Hitachi H8/500",
    431 		[EM_IA_64] = "Intel IA-64",
    432 		[EM_MIPS_X] = "Stanford MIPS-X",
    433 		[EM_COLDFIRE] = "Motorola ColdFire",
    434 		[EM_68HC12] = "Motorola M68HC12",
    435 		[EM_MMA] = "Fujitsu MMA",
    436 		[EM_PCP] = "Siemens PCP",
    437 		[EM_NCPU] = "Sony nCPU",
    438 		[EM_NDR1] = "Denso NDR1",
    439 		[EM_STARCORE] = "Motorola Star*Core",
    440 		[EM_ME16] = "Toyota ME16",
    441 		[EM_ST100] = "STMicroelectronics ST100",
    442 		[EM_TINYJ] = "Advanced Logic Corp. TinyJ",
    443 		[EM_X86_64] = "AMD x86-64",
    444 		[EM_PDSP] = "Sony DSP Processor",
    445 		[EM_PDP10] = "DEC PDP-10",
    446 		[EM_PDP11] = "DEC PDP-11",
    447 		[EM_FX66] = "Siemens FX66",
    448 		[EM_ST9PLUS] = "STMicroelectronics ST9+",
    449 		[EM_ST7] = "STMicroelectronics ST7",
    450 		[EM_68HC16] = "Motorola MC68HC16",
    451 		[EM_68HC11] = "Motorola MC68HC11",
    452 		[EM_68HC08] = "Motorola MC68HC08",
    453 		[EM_68HC05] = "Motorola MC68HC05",
    454 		[EM_SVX] = "Silicon Graphics SVx",
    455 		[EM_ST19] = "STMicroelectronics ST19",
    456 		[EM_VAX] = "Digital VAX",
    457 		[EM_CRIS] = "Axis Communications 32-bit",
    458 		[EM_JAVELIN] = "Infineon Technologies 32-bit",
    459 		[EM_FIREPATH] = "Element 14 64-bit DSP Processor",
    460 		[EM_ZSP] = "LSI Logic 16-bit DSP Processor",
    461 		[EM_MMIX] = "Donald Knuth's educational 64-bit",
    462 		[EM_HUANY] = "Harvard machine-independent",
    463 		[EM_PRISM] = "SiTera Prism",
    464 		[EM_AVR] = "Atmel AVR 8-bit",
    465 		[EM_FR30] = "Fujitsu FR30",
    466 		[EM_D10V] = "Mitsubishi D10V",
    467 		[EM_D30V] = "Mitsubishi D30V",
    468 		[EM_V850] = "NEC v850",
    469 		[EM_M32R] = "Mitsubishi M32R",
    470 		[EM_MN10300] = "Matsushita MN10300",
    471 		[EM_MN10200] = "Matsushita MN10200",
    472 		[EM_PJ] = "picoJava",
    473 		[EM_OPENRISC] = "OpenRISC 32-bit",
    474 		[EM_ARC_A5] = "ARC ARCompact",
    475 		[EM_ARC_COMPACT] = "ARC ARCompact",
    476 		[EM_XTENSA] = "Tensilica Xtensa",
    477 		[EM_VIDEOCORE] = "Alphamosaic VideoCore",
    478 		[EM_TMM_GPP] = "Thompson Multimedia GPP",
    479 		[EM_NS32K] = "National 32000 series",
    480 		[EM_TPC] = "Tenor Network TPC",
    481 		[EM_SNP1K] = "Trebia SNP 1000",
    482 		[EM_ST200] = "STMicroelectronics ST200",
    483 		[EM_IP2K] = "Ubicom IP2xxx",
    484 		[EM_MAX] = "MAX Processor",
    485 		[EM_CR] = "National CompactRISC",
    486 		[EM_F2MC16] = "Fujitsu F2MC16",
    487 		[EM_MSP430] = "Texas msp430",
    488 		[EM_BLACKFIN] = "Analog Devices Blackfin",
    489 		[EM_SE_C33] = "S1C33 of Seiko Epson",
    490 		[EM_SEP] = "Sharp embedded",
    491 		[EM_ARCA] = "Arca RISC",
    492 		[EM_UNICORE] = "PKU-Unity Ltd. and MPRC",
    493 		[EM_EXCESS] = "eXcess CPU",
    494 		[EM_DXP] = "Deep Execution Processor",
    495 		[EM_ALTERA_NIOS2] = "Altera Nios II",
    496 		[EM_CRX] = "National CompactRISC CRX",
    497 		[EM_XGATE] = "Motorola XGATE",
    498 		[EM_C166] = "Infineon C16x/XC16x",
    499 		[EM_M16C] = "Renesas M16C",
    500 		[EM_DSPIC30F] = "Microchip dsPIC30F",
    501 		[EM_CE] = "Freescale Communication Engine",
    502 		[EM_M32C] = "Renesas M32C",
    503 		[EM_TSK3000] = "Altium TSK3000 core",
    504 		[EM_RS08] = "Freescale RS08",
    505 		[EM_SHARC] = "Analog Devices SHARC",
    506 		[EM_ECOG2] = "Cyan Technology eCOG2",
    507 		[EM_SCORE7] = "Sunplus S+core7",
    508 		[EM_DSP24] = "NJR 24-bit DSP",
    509 		[EM_VIDEOCORE3] = "Broadcom VideoCore III",
    510 		[EM_LATTICEMICO3] = "RISC processor for Lattice FPGA",
    511 		[EM_SE_C17] = "Seiko Epson C17",
    512 		[EM_TI_C6000] = "TMS320C6000 DSP family",
    513 		[EM_TI_C2000] = "TMS320C2000 DSP family",
    514 		[EM_TI_C5500] = "TMS320C55x DSP family",
    515 		[EM_TI_ARP32] = "Texas Application Specific RISC",
    516 		[EM_TI_PRU] = "Texas Programmable Realtime Unit",
    517 		[EM_MMDSP_PLUS] = "STMicroelectronics 64bit VLIW",
    518 		[EM_CYPRESS_M8C] = "Cypress M8C microprocessor",
    519 		[EM_R32C] = "Renesas R32C series",
    520 		[EM_TRIMEDIA] = "NXP Semiconductors TriMedia",
    521 		[EM_QDSP6] = "QUALCOMM DSP6 Processor",
    522 		[EM_8051] = "Intel 8051 and variants",
    523 		[EM_STXP7X] = "STMicroelectronics STxP7x",
    524 		[EM_NDS32] = "Andes Technology embedded RISC",
    525 		[EM_ECOG1] = "Cyan Technology eCOG1X family",
    526 		[EM_ECOG1X] = "Cyan Technology eCOG1X family",
    527 		[EM_MAXQ30] = "MAXQ30 Core Micro-controllers",
    528 		[EM_XIMO16] = "NJR 16-bit DSP Processor",
    529 		[EM_MANIK] = "M2000 Reconfigurable RISC",
    530 		[EM_CRAYNV2] = "Cray Inc. NV2 vector architecture",
    531 		[EM_RX] = "Renesas RX family",
    532 		[EM_METAG] = "Imagination Technologies META",
    533 		[EM_MCST_ELBRUS] = "MCST Elbrus",
    534 		[EM_ECOG16] = "Cyan Technology eCOG16 family",
    535 		[EM_CR16] = "National CompactRISC CR16",
    536 		[EM_ETPU] = "Freescale Extended Time Unit",
    537 		[EM_SLE9X] = "Infineon Technologies SLE9X core",
    538 		[EM_L10M] = "Intel L10M",
    539 		[EM_K10M] = "Intel K10M",
    540 		[EM_AARCH64] = "ARM AARCH64",
    541 		[EM_AVR32] = "Atmel 32-bit",
    542 		[EM_STM8] = "STMicroeletronics STM8 ",
    543 		[EM_TILE64] = "Tilera TILE64",
    544 		[EM_TILEPRO] = "Tilera TILEPro",
    545 		[EM_MICROBLAZE] = "Xilinx MicroBlaze 32-bit",
    546 		[EM_CUDA] = "NVIDIA CUDA architecture",
    547 		[EM_TILEGX] = "Tilera TILE-Gx family",
    548 		[EM_CLOUDSHIELD] = "CloudShield architecture family",
    549 		[EM_COREA_1ST] = "KIPO-KAIST Core-A 1st gen family",
    550 		[EM_COREA_2ND] = "KIPO-KAIST Core-A 2nd gen family",
    551 		[EM_ARC_COMPACT2] = "Synopsys ARCompact V2",
    552 		[EM_OPEN8] = "Open8 8-bit RISC soft processor core",
    553 		[EM_RL78] = "Renesas RL78 family",
    554 		[EM_VIDEOCORE5] = "Broadcom VideoCore V processor",
    555 		[EM_78KOR] = "Renesas 78KOR family",
    556 		[EM_56800EX] = "Freescale 56800EX (DSC)",
    557 		[EM_BA1] = "Beyond BA1 CPU architecture",
    558 		[EM_BA2] = "Beyond BA2 CPU architecture",
    559 		[EM_XCORE] = "XMOS xCORE processor family",
    560 		[EM_MCHP_PIC] = "Microchip 8-bit PIC(r) family",
    561 		[EM_KM32] = "KM211 KM32 32-bit processor",
    562 		[EM_KMX32] = "KM211 KMX32 32-bit processor",
    563 		[EM_KMX16] = "KM211 KMX16 16-bit processor",
    564 		[EM_KMX8] = "KM211 KMX8 8-bit processor",
    565 		[EM_KVARC] = "KM211 KVARC processor",
    566 		[EM_CDP] = "Paneve CDP architecture family",
    567 		[EM_COGE] = "Cognitive Smart Memory Processor",
    568 		[EM_COOL] = "Bluechip Systems CoolEngine",
    569 		[EM_NORC] = "Nanoradio Optimized RISC",
    570 		[EM_CSR_KALIMBA] = "CSR Kalimba architecture family",
    571 		[EM_Z80] = "Zilog Z80",
    572 		[EM_VISIUM] = "VISIUMcore processor",
    573 		[EM_FT32] = "FTDI Chip FT32",
    574 		[EM_MOXIE] = "Moxie processor family",
    575 		[EM_AMDGPU] = "AMD GPU architecture",
    576 		[EM_RISCV] = "RISC-V",
    577 		[EM_BPF] = "Linux BPF",
    578 		[EM_CSKY] = "C-SKY",
    579 	};
    580 	static char *versions[] = {
    581 		[EV_NONE] = "Invalid",
    582 		[EV_CURRENT] = "Current",
    583 	};
    584 
    585 	class = hdr->ident[EI_CLASS];
    586 	data = hdr->ident[EI_DATA];
    587 	abi = hdr->ident[EI_OSABI];
    588 	type = hdr->type;
    589 	mach = hdr->machine;
    590 	version = hdr->version;
    591 
    592 	sclass = (class <= ELFCLASS64) ? classes[class] : "Unknown";
    593 	sdata = (data <= ELFDATA2MSB) ? datas[data] : "Unknown";
    594 	stype = (type <= ET_CORE) ? types[type] : "Unknown";
    595 	smach = (mach <= EM_CSKY) ? machs[mach] : "Unknown";
    596 	if (!smach)
    597 		smach = "Unknown";
    598 	sversion = (version <= EV_CURRENT) ? versions[version] : "Unknown";
    599 
    600 	switch (abi) {
    601 	case ELFOSABI_ARM:
    602 		sabi = "ARM";
    603 		break;
    604 	case ELFOSABI_STANDALONE:
    605 		sabi = "Standalone (embedded) application";
    606 		break;
    607 	default:
    608 		sabi = (abi <= ELFOSABI_OPENVOS) ? abis[abi] : "Unknown";
    609 	}
    610 
    611 	printf("elfhdr:\n"
    612 	       "\tei_class: %u, %s\n"
    613 	       "\tei_data: %u, %s\n"
    614 	       "\tei_version: %u\n"
    615 	       "\tei_osabi: %u, %s\n"
    616 	       "\tei_abiversion: %u\n"
    617 	       "\te_type: %u, %s\n"
    618 	       "\te_machine: %u, %s\n"
    619 	       "\te_version: %lu, %s\n"
    620 	       "\te_entry: 0x%08llx\n"
    621 	       "\te_phoff: %llu\n"
    622 	       "\te_shoff: %llu\n"
    623 	       "\te_flags: %#lx\n"
    624 	       "\te_ehsize: %lu\n"
    625 	       "\te_phentsize: %lu\n"
    626 	       "\te_phnum: %lu\n"
    627 	       "\te_shentsize: %lu\n"
    628 	       "\te_shnum: %lu\n"
    629 	       "\te_shstrndx: %lu\n"
    630 	       "\n",
    631 	       class, sclass,
    632 	       data, sdata,
    633 	       hdr->ident[EI_VERSION],
    634 	       abi, sabi,
    635 	       hdr->ident[EI_ABIVERSION],
    636 	       type, stype,
    637 	       mach, smach,
    638 	       version, sversion,
    639 	       (long long) hdr->entry,
    640 	       (long long) hdr->phoff,
    641 	       (long long) hdr->shoff,
    642 	       (long) hdr->flags,
    643 	       (long) hdr->ehsize,
    644 	       (long) hdr->phentsize,
    645 	       (long) hdr->phnum,
    646 	       (long) hdr->shentsize,
    647 	       (long) hdr->shnum,
    648 	       (long) hdr->shstrndx);
    649 }
    650 
    651 static void
    652 printphdr(Obj *obj, Elfphdr *phdr, unsigned long n)
    653 {
    654 	int j;
    655 	Map *map;
    656 	Mapsec *seg;
    657 	unsigned long i;
    658 	static char *types[] = {
    659 		[PT_NULL] = "unused",
    660 		[PT_LOAD] = "loadable segment",
    661 		[PT_DYNAMIC] = "dynamic linking section",
    662 		[PT_INTERP] = "the RTLD",
    663 		[PT_NOTE] = "note information",
    664 		[PT_SHLIB] = "reserved - purpose undefined",
    665 		[PT_PHDR] = "program header",
    666 		[PT_TLS] = "thread local storage",
    667 	};
    668 	static Flags f ={
    669 		.nr = NR_RIGHTS,
    670 		.text = {
    671 			[FLAG_X] = "Executable",
    672 			[FLAG_W] = "Writable",
    673 			[FLAG_R] = "Readable",
    674 		}
    675 	};
    676 
    677 	if ((map = loadmap(obj, NULL)) == NULL) {
    678 		error("getting the object memory map");
    679 		return;
    680 	}
    681 
    682 	for (i = 0; i < n; i++) {
    683 		char *stype;
    684 		unsigned long type;
    685 
    686 		f.flags = phdr->flags;
    687 		type = phdr->type;
    688 		if (type <= PT_TLS) {
    689 			stype = types[type];
    690 		} else {
    691 			switch (type) {
    692 			case PT_GNU_EH_FRAME:
    693 				stype = "Frame unwind information";
    694 				break;
    695 			case PT_GNU_STACK:
    696 				stype = "Stack flags";
    697 				break;
    698 			case PT_GNU_RELRO:
    699 				stype = "Read-only after relocation";
    700 				break;
    701 			case PT_GNU_PROPERTY:
    702 				stype = "GNU property";
    703 				break;
    704 			default:
    705 				stype = "Unknown";
    706 				break;
    707 			}
    708 		}
    709 
    710 		printf("Program header %ld\n"
    711 		       "\tp_type: %#lx, %s\n"
    712 		       "\tp_flags: %#lx\n"
    713 		       "\tp_offset: %#08llx\n"
    714 		       "\tp_vaddr: %#08llx\n"
    715 		       "\tp_paddr: %#08llx\n"
    716 		       "\tp_filesz: %#08llx\n"
    717 		       "\tp_memsz: %#08llx\n"
    718 		       "\tp_align: %#08llx\n",
    719 		       i,
    720 		       type, stype,
    721 		       (long) phdr->flags,
    722 		       (long long) phdr->offset,
    723 		       (long long) phdr->vaddr,
    724 		       (long long) phdr->paddr,
    725 		       (long long) phdr->filesz,
    726 		       (long long) phdr->memsz,
    727 		       (long long) phdr->align);
    728 
    729 		putchar('\t');
    730 		printflags(&f);
    731 
    732 		seg = &map->seg[i];
    733 		printf("\tSections:");
    734 		for (j = 0; j < seg->nchild; ++j)
    735 			printf(" %d", seg->child[j]->sec.index);
    736 		putchar('\n');
    737 		putchar('\n');
    738 
    739 		++phdr;
    740 	}
    741 
    742 	puts("Section to Segment mapping:\nSegment\tSections");
    743 	for (i = 0; i < n; ++i) {
    744 		printf(" %02lu\t", i);
    745 
    746 		seg = &map->seg[i];
    747 		for (j = 0; j < seg->nchild; ++j)
    748 			printf(" %s", seg->child[j]->sec.name);
    749 		putchar('\n');
    750 	}
    751 	putchar('\n');
    752 
    753 	delmap(map);
    754 }
    755 
    756 void
    757 elffhdr(Obj *obj, unsigned long long *start, Flags *f)
    758 {
    759 	size_t i;
    760 	char *name;
    761 	Elf *elf = obj->data;
    762 	Elfhdr *hdr = &elf->hdr;
    763 	Elfsec *shdr;
    764 
    765 	*start = hdr->entry;
    766 
    767 	for (i = 0; i < elf->nsec; i++) {
    768 		shdr = &elf->secs[i];
    769 		name = shdr->name;
    770 		setflag(f, strncmp(name, ".debug", 6) == 0, HAS_DEBUG);
    771 		setflag(f, strncmp(name, ".line", 5) == 0, HAS_LINENO);
    772 		setflag(f, strcmp(name, ".debug_line") == 0, HAS_LINENO);
    773 		setflag(f, shdr->type == SHT_RELA, HAS_RELOC);
    774 		setflag(f, shdr->type == SHT_REL, HAS_RELOC);
    775 	}
    776 
    777 	setflag(f, hdr->type == ET_EXEC, EXEC_P);
    778 	setflag(f, hdr->type == ET_DYN, DYNAMIC);
    779 	setflag(f, elf->nsym > 0, HAS_SYMS);
    780 
    781 	if (!pflag)
    782 		return;
    783 
    784 	printfhdr(hdr);
    785 	printphdr(obj, elf->phdr, hdr->phnum);
    786 }