relocs.c revision 908ec7afacfdc83dc10938ed1d3c38b3526034ec
1968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <stdio.h>
2968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <stdarg.h>
3968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <stdlib.h>
4968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <stdint.h>
5968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <string.h>
6968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <errno.h>
7968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <unistd.h>
8968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <elf.h>
9968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <byteswap.h>
10968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define USE_BSD
11968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#include <endian.h>
12968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
13ca820181fc187af316a18b2700582663662c4012Robert P. J. Day#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
14968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic Elf32_Ehdr ehdr;
15968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic unsigned long reloc_count, reloc_idx;
16968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic unsigned long *relocs;
17968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
18908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvinstruct section {
19908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	Elf32_Shdr     shdr;
20908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	struct section *link;
21908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	Elf32_Sym      *symtab;
22908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	Elf32_Rel      *reltab;
23908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	char           *strtab;
24908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin};
25908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvinstatic struct section *secs;
26908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin
276a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal/*
286a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * Following symbols have been audited. There values are constant and do
296a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * not change if bzImage is loaded at a different physical address than
306a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * the address for which it has been compiled. Don't warn user about
316a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal * absolute relocations present w.r.t these symbols.
326a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal */
336a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyalstatic const char* safe_abs_relocs[] = {
34600b2fc242992e552e0b4e24c8c1f084b341f39bJeremy Fitzhardinge		"xen_irq_disable_direct_reloc",
35600b2fc242992e552e0b4e24c8c1f084b341f39bJeremy Fitzhardinge		"xen_save_fl_direct_reloc",
366a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal};
376a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
386a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyalstatic int is_safe_abs_reloc(const char* sym_name)
396a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal{
404d022adab4511892226f1eae00a44502bf685ae5Alejandro Martinez Ruiz	int i;
416a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
42908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 0; i < ARRAY_SIZE(safe_abs_relocs); i++) {
436a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal		if (!strcmp(sym_name, safe_abs_relocs[i]))
446a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			/* Match found */
456a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			return 1;
466a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	}
474707c4717a5a6f375f3300bbccff1d46dcf75b25Roland McGrath	if (strncmp(sym_name, "VDSO", 4) == 0)
484707c4717a5a6f375f3300bbccff1d46dcf75b25Roland McGrath		return 1;
492a3d4f1f1f839e354ebd7d40b2d5d8ac8481a930Al Viro	if (strncmp(sym_name, "__crc_", 6) == 0)
502a3d4f1f1f839e354ebd7d40b2d5d8ac8481a930Al Viro		return 1;
516a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	return 0;
526a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal}
536a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
54968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void die(char *fmt, ...)
55968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
56968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	va_list ap;
57968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	va_start(ap, fmt);
58968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	vfprintf(stderr, fmt, ap);
59968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	va_end(ap);
60968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	exit(1);
61968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
62968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
63968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sym_type(unsigned type)
64968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
65968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	static const char *type_name[] = {
66968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define SYM_TYPE(X) [X] = #X
67968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_TYPE(STT_NOTYPE),
68968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_TYPE(STT_OBJECT),
69968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_TYPE(STT_FUNC),
70968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_TYPE(STT_SECTION),
71968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_TYPE(STT_FILE),
72968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_TYPE(STT_COMMON),
73968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_TYPE(STT_TLS),
74968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#undef SYM_TYPE
75968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	};
76968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const char *name = "unknown sym type name";
77ca820181fc187af316a18b2700582663662c4012Robert P. J. Day	if (type < ARRAY_SIZE(type_name)) {
78968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		name = type_name[type];
79968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
80968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return name;
81968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
82968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
83968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sym_bind(unsigned bind)
84968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
85968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	static const char *bind_name[] = {
86968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define SYM_BIND(X) [X] = #X
87968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_BIND(STB_LOCAL),
88968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_BIND(STB_GLOBAL),
89968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_BIND(STB_WEAK),
90968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#undef SYM_BIND
91968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	};
92968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const char *name = "unknown sym bind name";
93ca820181fc187af316a18b2700582663662c4012Robert P. J. Day	if (bind < ARRAY_SIZE(bind_name)) {
94968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		name = bind_name[bind];
95968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
96968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return name;
97968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
98968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
99968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sym_visibility(unsigned visibility)
100968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
101968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	static const char *visibility_name[] = {
102968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define SYM_VISIBILITY(X) [X] = #X
103968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_VISIBILITY(STV_DEFAULT),
104968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_VISIBILITY(STV_INTERNAL),
105968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_VISIBILITY(STV_HIDDEN),
106968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		SYM_VISIBILITY(STV_PROTECTED),
107968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#undef SYM_VISIBILITY
108968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	};
109968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const char *name = "unknown sym visibility name";
110ca820181fc187af316a18b2700582663662c4012Robert P. J. Day	if (visibility < ARRAY_SIZE(visibility_name)) {
111968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		name = visibility_name[visibility];
112968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
113968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return name;
114968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
115968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
116968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *rel_type(unsigned type)
117968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
118968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	static const char *type_name[] = {
119968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define REL_TYPE(X) [X] = #X
120968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_NONE),
121968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_32),
122968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_PC32),
123968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_GOT32),
124968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_PLT32),
125968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_COPY),
126968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_GLOB_DAT),
127968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_JMP_SLOT),
128968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_RELATIVE),
129968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_GOTOFF),
130968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		REL_TYPE(R_386_GOTPC),
131968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#undef REL_TYPE
132968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	};
133968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const char *name = "unknown type rel type name";
134ca820181fc187af316a18b2700582663662c4012Robert P. J. Day	if (type < ARRAY_SIZE(type_name)) {
135968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		name = type_name[type];
136968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
137968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return name;
138968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
139968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
140968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sec_name(unsigned shndx)
141968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
142968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const char *sec_strtab;
143968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const char *name;
144908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	sec_strtab = secs[ehdr.e_shstrndx].strtab;
145968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	name = "<noname>";
146968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (shndx < ehdr.e_shnum) {
147908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		name = sec_strtab + secs[shndx].shdr.sh_name;
148968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
149968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	else if (shndx == SHN_ABS) {
150968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		name = "ABSOLUTE";
151968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
152968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	else if (shndx == SHN_COMMON) {
153968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		name = "COMMON";
154968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
155968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return name;
156968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
157968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
158968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
159968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
160968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const char *name;
161968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	name = "<noname>";
162968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (sym->st_name) {
163968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		name = sym_strtab + sym->st_name;
164968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
165968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	else {
166908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		name = sec_name(secs[sym->st_shndx].shdr.sh_name);
167968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
168968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return name;
169968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
170968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
171968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
172968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
173968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#if BYTE_ORDER == LITTLE_ENDIAN
174968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define le16_to_cpu(val) (val)
175968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define le32_to_cpu(val) (val)
176968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#endif
177968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#if BYTE_ORDER == BIG_ENDIAN
178968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define le16_to_cpu(val) bswap_16(val)
179968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#define le32_to_cpu(val) bswap_32(val)
180968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman#endif
181968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
182968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic uint16_t elf16_to_cpu(uint16_t val)
183968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
184968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return le16_to_cpu(val);
185968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
186968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
187968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic uint32_t elf32_to_cpu(uint32_t val)
188968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
189968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return le32_to_cpu(val);
190968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
191968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
192968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_ehdr(FILE *fp)
193968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
194968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) {
195968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Cannot read ELF header: %s\n",
196968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			strerror(errno));
197968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
1988bd1796dedd50abd7553afbe6113bd97cc88390fCyrill Gorcunov	if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) {
199968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("No ELF magic\n");
200968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
201968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_ident[EI_CLASS] != ELFCLASS32) {
202968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Not a 32 bit executable\n");
203968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
204968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
205968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Not a LSB ELF executable\n");
206968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
207968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
208968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Unknown ELF version\n");
209968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
210968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	/* Convert the fields to native endian */
211968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_type      = elf16_to_cpu(ehdr.e_type);
212968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_machine   = elf16_to_cpu(ehdr.e_machine);
213968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_version   = elf32_to_cpu(ehdr.e_version);
214968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_entry     = elf32_to_cpu(ehdr.e_entry);
215968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_phoff     = elf32_to_cpu(ehdr.e_phoff);
216968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_shoff     = elf32_to_cpu(ehdr.e_shoff);
217968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_flags     = elf32_to_cpu(ehdr.e_flags);
218968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_ehsize    = elf16_to_cpu(ehdr.e_ehsize);
219968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_phentsize = elf16_to_cpu(ehdr.e_phentsize);
220968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_phnum     = elf16_to_cpu(ehdr.e_phnum);
221968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_shentsize = elf16_to_cpu(ehdr.e_shentsize);
222968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_shnum     = elf16_to_cpu(ehdr.e_shnum);
223968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	ehdr.e_shstrndx  = elf16_to_cpu(ehdr.e_shstrndx);
224968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
225968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if ((ehdr.e_type != ET_EXEC) && (ehdr.e_type != ET_DYN)) {
226968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Unsupported ELF header type\n");
227968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
228968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_machine != EM_386) {
229968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Not for x86\n");
230968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
231968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_version != EV_CURRENT) {
232968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Unknown ELF version\n");
233968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
234968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_ehsize != sizeof(Elf32_Ehdr)) {
235968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Bad Elf header size\n");
236968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
237968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_phentsize != sizeof(Elf32_Phdr)) {
238968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Bad program header entry\n");
239968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
240968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_shentsize != sizeof(Elf32_Shdr)) {
241968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Bad section header entry\n");
242968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
243968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (ehdr.e_shstrndx >= ehdr.e_shnum) {
244968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("String table index out of bounds\n");
245968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
246968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
247968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
248968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_shdrs(FILE *fp)
249968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
250968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int i;
251908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	Elf32_Shdr shdr;
252908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin
253908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	secs = calloc(ehdr.e_shnum, sizeof(struct section));
254908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	if (!secs) {
255908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		die("Unable to allocate %d section headers\n",
256908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		    ehdr.e_shnum);
257968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
258968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) {
259968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Seek to %d failed: %s\n",
260968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			ehdr.e_shoff, strerror(errno));
261968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
262908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 0; i < ehdr.e_shnum; i++) {
263908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec = &secs[i];
264908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (fread(&shdr, sizeof shdr, 1, fp) != 1)
265908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			die("Cannot read ELF section headers %d/%d: %s\n",
266908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			    i, ehdr.e_shnum, strerror(errno));
267908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_name      = elf32_to_cpu(shdr.sh_name);
268908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_type      = elf32_to_cpu(shdr.sh_type);
269908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_flags     = elf32_to_cpu(shdr.sh_flags);
270908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_addr      = elf32_to_cpu(shdr.sh_addr);
271908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_offset    = elf32_to_cpu(shdr.sh_offset);
272908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_size      = elf32_to_cpu(shdr.sh_size);
273908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_link      = elf32_to_cpu(shdr.sh_link);
274908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_info      = elf32_to_cpu(shdr.sh_info);
275908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_addralign = elf32_to_cpu(shdr.sh_addralign);
276908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->shdr.sh_entsize   = elf32_to_cpu(shdr.sh_entsize);
277908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (sec->shdr.sh_link < ehdr.e_shnum)
278908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			sec->link = &secs[sec->shdr.sh_link];
279968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
280968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
281968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
282968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
283968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_strtabs(FILE *fp)
284968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
285968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int i;
286908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 0; i < ehdr.e_shnum; i++) {
287908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec = &secs[i];
288908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (sec->shdr.sh_type != SHT_STRTAB) {
289968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
290968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
291908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->strtab = malloc(sec->shdr.sh_size);
292908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (!sec->strtab) {
293968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("malloc of %d bytes for strtab failed\n",
294908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin				sec->shdr.sh_size);
295968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
296908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
297968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("Seek to %d failed: %s\n",
298908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin				sec->shdr.sh_offset, strerror(errno));
299968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
300908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (fread(sec->strtab, 1, sec->shdr.sh_size, fp)
301908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		    != sec->shdr.sh_size) {
302968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("Cannot read symbol table: %s\n",
303968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				strerror(errno));
304968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
305968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
306968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
307968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
308968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_symtabs(FILE *fp)
309968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
310968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int i,j;
311908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 0; i < ehdr.e_shnum; i++) {
312908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec = &secs[i];
313908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (sec->shdr.sh_type != SHT_SYMTAB) {
314968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
315968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
316908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->symtab = malloc(sec->shdr.sh_size);
317908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (!sec->symtab) {
318968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("malloc of %d bytes for symtab failed\n",
319908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin				sec->shdr.sh_size);
320968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
321908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
322968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("Seek to %d failed: %s\n",
323908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin				sec->shdr.sh_offset, strerror(errno));
324968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
325908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (fread(sec->symtab, 1, sec->shdr.sh_size, fp)
326908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		    != sec->shdr.sh_size) {
327968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("Cannot read symbol table: %s\n",
328968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				strerror(errno));
329968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
330908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
331908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			Elf32_Sym *sym = &sec->symtab[j];
332908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			sym->st_name  = elf32_to_cpu(sym->st_name);
333908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			sym->st_value = elf32_to_cpu(sym->st_value);
334908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			sym->st_size  = elf32_to_cpu(sym->st_size);
335908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			sym->st_shndx = elf16_to_cpu(sym->st_shndx);
336968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
337968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
338968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
339968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
340968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
341968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void read_relocs(FILE *fp)
342968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
343968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int i,j;
344908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 0; i < ehdr.e_shnum; i++) {
345908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec = &secs[i];
346908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (sec->shdr.sh_type != SHT_REL) {
347968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
348968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
349908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec->reltab = malloc(sec->shdr.sh_size);
350908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (!sec->reltab) {
351968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("malloc of %d bytes for relocs failed\n",
352908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin				sec->shdr.sh_size);
353968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
354908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) {
355968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("Seek to %d failed: %s\n",
356908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin				sec->shdr.sh_offset, strerror(errno));
357968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
358908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (fread(sec->reltab, 1, sec->shdr.sh_size, fp)
359908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		    != sec->shdr.sh_size) {
360968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			die("Cannot read symbol table: %s\n",
361968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				strerror(errno));
362968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
363908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
364908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			Elf32_Rel *rel = &sec->reltab[j];
365908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			rel->r_offset = elf32_to_cpu(rel->r_offset);
366908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			rel->r_info   = elf32_to_cpu(rel->r_info);
367968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
368968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
369968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
370968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
371968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
372968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void print_absolute_symbols(void)
373968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
374968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int i;
375968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	printf("Absolute symbols\n");
376968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	printf(" Num:    Value Size  Type       Bind        Visibility  Name\n");
377908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 0; i < ehdr.e_shnum; i++) {
378908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec = &secs[i];
379968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		char *sym_strtab;
380968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		Elf32_Sym *sh_symtab;
381968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		int j;
382908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin
383908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (sec->shdr.sh_type != SHT_SYMTAB) {
384968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
385968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
386908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sh_symtab = sec->symtab;
387908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sym_strtab = sec->link->strtab;
388908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Sym); j++) {
389968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			Elf32_Sym *sym;
390968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			const char *name;
391908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			sym = &sec->symtab[j];
392968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			name = sym_name(sym_strtab, sym);
393968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			if (sym->st_shndx != SHN_ABS) {
394968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				continue;
395968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			}
396968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			printf("%5d %08x %5d %10s %10s %12s %s\n",
397968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				j, sym->st_value, sym->st_size,
398968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				sym_type(ELF32_ST_TYPE(sym->st_info)),
399968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				sym_bind(ELF32_ST_BIND(sym->st_info)),
400968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				sym_visibility(ELF32_ST_VISIBILITY(sym->st_other)),
401968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				name);
402968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
403968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
404968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	printf("\n");
405968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
406968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
407968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void print_absolute_relocs(void)
408968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
4096a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	int i, printed = 0;
4106a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
411908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 0; i < ehdr.e_shnum; i++) {
412908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec = &secs[i];
413908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec_applies, *sec_symtab;
414968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		char *sym_strtab;
415968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		Elf32_Sym *sh_symtab;
416968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		int j;
417908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (sec->shdr.sh_type != SHT_REL) {
418968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
419968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
420908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec_symtab  = sec->link;
421908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec_applies = &secs[sec->shdr.sh_info];
422908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
423968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
424968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
425908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sh_symtab  = sec_symtab->symtab;
426908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sym_strtab = sec_symtab->link->strtab;
427908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
428968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			Elf32_Rel *rel;
429968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			Elf32_Sym *sym;
430968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			const char *name;
431908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			rel = &sec->reltab[j];
432968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
433968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			name = sym_name(sym_strtab, sym);
434968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			if (sym->st_shndx != SHN_ABS) {
435968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				continue;
436968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			}
4376a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
4386a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			/* Absolute symbols are not relocated if bzImage is
4396a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * loaded at a non-compiled address. Display a warning
4406a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * to user at compile time about the absolute
4416a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * relocations present.
4426a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 *
4436a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * User need to audit the code to make sure
4446a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * some symbols which should have been section
4456a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * relative have not become absolute because of some
4466a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * linker optimization or wrong programming usage.
4476a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 *
4486a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * Before warning check if this absolute symbol
4496a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 * relocation is harmless.
4506a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			 */
4516a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			if (is_safe_abs_reloc(name))
4526a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal				continue;
4536a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
4546a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			if (!printed) {
4556a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal				printf("WARNING: Absolute relocations"
4566a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal					" present\n");
4576a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal				printf("Offset     Info     Type     Sym.Value "
4586a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal					"Sym.Name\n");
4596a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal				printed = 1;
4606a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			}
4616a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
462968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			printf("%08x %08x %10s %08x  %s\n",
463968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				rel->r_offset,
464968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				rel->r_info,
465968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				rel_type(ELF32_R_TYPE(rel->r_info)),
466968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				sym->st_value,
467968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				name);
468968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
469968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
4706a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
4716a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	if (printed)
4726a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal		printf("\n");
473968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
474968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
475968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void walk_relocs(void (*visit)(Elf32_Rel *rel, Elf32_Sym *sym))
476968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
477968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int i;
478968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	/* Walk through the relocations */
479908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 0; i < ehdr.e_shnum; i++) {
480968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		char *sym_strtab;
481968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		Elf32_Sym *sh_symtab;
482908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec_applies, *sec_symtab;
483968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		int j;
484908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		struct section *sec = &secs[i];
485908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin
486908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (sec->shdr.sh_type != SHT_REL) {
487968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
488968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
489908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec_symtab  = sec->link;
490908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sec_applies = &secs[sec->shdr.sh_info];
491908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) {
492968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
493968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
494908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sh_symtab = sec_symtab->symtab;
495908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		sym_strtab = sec->link->strtab;
496908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		for (j = 0; j < sec->shdr.sh_size/sizeof(Elf32_Rel); j++) {
497968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			Elf32_Rel *rel;
498968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			Elf32_Sym *sym;
499968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			unsigned r_type;
500908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin			rel = &sec->reltab[j];
501968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			sym = &sh_symtab[ELF32_R_SYM(rel->r_info)];
502968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			r_type = ELF32_R_TYPE(rel->r_info);
503968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			/* Don't visit relocations to absolute symbols */
504968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			if (sym->st_shndx == SHN_ABS) {
505968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				continue;
506968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			}
507968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			if (r_type == R_386_PC32) {
508968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				/* PC relative relocations don't need to be adjusted */
509968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			}
510968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			else if (r_type == R_386_32) {
511968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				/* Visit relocations that need to be adjusted */
512968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				visit(rel, sym);
513968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			}
514968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			else {
515968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				die("Unsupported relocation type: %d\n", r_type);
516968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			}
517968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
518968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
519968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
520968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
521968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void count_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
522968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
523968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	reloc_count += 1;
524968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
525968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
526968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void collect_reloc(Elf32_Rel *rel, Elf32_Sym *sym)
527968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
528968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	/* Remember the address that needs to be adjusted. */
529968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	relocs[reloc_idx++] = rel->r_offset;
530968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
531968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
532968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic int cmp_relocs(const void *va, const void *vb)
533968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
534968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const unsigned long *a, *b;
535968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	a = va; b = vb;
536968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return (*a == *b)? 0 : (*a > *b)? 1 : -1;
537968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
538968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
539968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void emit_relocs(int as_text)
540968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
541968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int i;
542968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	/* Count how many relocations I have and allocate space for them. */
543968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	reloc_count = 0;
544968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	walk_relocs(count_reloc);
545968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	relocs = malloc(reloc_count * sizeof(relocs[0]));
546968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (!relocs) {
547968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("malloc of %d entries for relocs failed\n",
548968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			reloc_count);
549968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
550968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	/* Collect up the relocations */
551968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	reloc_idx = 0;
552968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	walk_relocs(collect_reloc);
553968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
554968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	/* Order the relocations for more efficient processing */
555968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	qsort(relocs, reloc_count, sizeof(relocs[0]), cmp_relocs);
556968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
557968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	/* Print the relocations */
558968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (as_text) {
559968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		/* Print the relocations in a form suitable that
560968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		 * gas will like.
561968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		 */
562968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		printf(".section \".data.reloc\",\"a\"\n");
563968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		printf(".balign 4\n");
564908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		for (i = 0; i < reloc_count; i++) {
565968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			printf("\t .long 0x%08lx\n", relocs[i]);
566968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
567968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		printf("\n");
568968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
569968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	else {
570968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		unsigned char buf[4];
571968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		buf[0] = buf[1] = buf[2] = buf[3] = 0;
572968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		/* Print a stop */
573968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
574968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		/* Now print each relocation */
575908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin		for (i = 0; i < reloc_count; i++) {
576968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			buf[0] = (relocs[i] >>  0) & 0xff;
577968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			buf[1] = (relocs[i] >>  8) & 0xff;
578968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			buf[2] = (relocs[i] >> 16) & 0xff;
579968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			buf[3] = (relocs[i] >> 24) & 0xff;
580968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			printf("%c%c%c%c", buf[0], buf[1], buf[2], buf[3]);
581968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
582968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
583968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
584968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
585968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanstatic void usage(void)
586968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
5876a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	die("relocs [--abs-syms |--abs-relocs | --text] vmlinux\n");
588968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
589968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
590968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biedermanint main(int argc, char **argv)
591968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman{
5926a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	int show_absolute_syms, show_absolute_relocs;
593968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int as_text;
594968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	const char *fname;
595968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	FILE *fp;
596968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	int i;
597968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman
5986a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	show_absolute_syms = 0;
5996a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	show_absolute_relocs = 0;
600968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	as_text = 0;
601968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	fname = NULL;
602908ec7afacfdc83dc10938ed1d3c38b3526034ecH. Peter Anvin	for (i = 1; i < argc; i++) {
603968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		char *arg = argv[i];
604968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		if (*arg == '-') {
6056a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			if (strcmp(argv[1], "--abs-syms") == 0) {
6066a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal				show_absolute_syms = 1;
6076a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal				continue;
6086a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			}
6096a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal
6106a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal			if (strcmp(argv[1], "--abs-relocs") == 0) {
6116a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal				show_absolute_relocs = 1;
612968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				continue;
613968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			}
614968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			else if (strcmp(argv[1], "--text") == 0) {
615968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				as_text = 1;
616968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman				continue;
617968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			}
618968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
619968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		else if (!fname) {
620968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			fname = arg;
621968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			continue;
622968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		}
623968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		usage();
624968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
625968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (!fname) {
626968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		usage();
627968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
628968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	fp = fopen(fname, "r");
629968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	if (!fp) {
630968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		die("Cannot open %s: %s\n",
631968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman			fname, strerror(errno));
632968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
633968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	read_ehdr(fp);
634968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	read_shdrs(fp);
635968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	read_strtabs(fp);
636968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	read_symtabs(fp);
637968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	read_relocs(fp);
6386a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	if (show_absolute_syms) {
639968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		print_absolute_symbols();
6406a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal		return 0;
6416a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	}
6426a044b3a0a1829ef19bb29548ffe553f48e8d80cVivek Goyal	if (show_absolute_relocs) {
643968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		print_absolute_relocs();
644968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman		return 0;
645968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	}
646968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	emit_relocs(as_text);
647968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman	return 0;
648968de4f02621db35b8ae5239c8cfc6664fb872d8Eric W. Biederman}
649