scc

A fork of https://git.simple-cc.org/scc/ for Qute

git clone https://git.8pit.net/scc.git

  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
 15enum 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
 30enum phdrflags {
 31	FLAG_X = 0,
 32	FLAG_W = 1,
 33	FLAG_R = 2,
 34	NR_RIGHTS = 3,
 35};
 36
 37int
 38elfhasrelloc(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
 55static void
 56printents(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
147static void
148printstbl(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
228void
229elfsyms(Obj *obj)
230{
231	printstbl(obj);
232
233	if (pflag)
234		printents(obj);
235}
236
237void
238elfscns(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
350static void
351printfhdr(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
651static void
652printphdr(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
756void
757elffhdr(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}