aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/boot
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /arch/x86/boot
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'arch/x86/boot')
-rw-r--r--arch/x86/boot/compressed/relocs.c682
1 files changed, 682 insertions, 0 deletions
</
diff --git a/arch/x86/boot/compressed/relocs.c b/arch/x86/boot/compressed/relocs.c
new file mode 100644
index 00000000000..89bbf4e4d05
--- /dev/null
+++ b/arch/x86/boot/compressed/relocs.c
@@ -0,0 +1,682 @@
1#include <stdio.h>
2#include <stdarg.h>
3#include <stdlib.h>
4#include <stdint.h>
5#include <string.h>
6#include <errno.h>
7#include <unistd.h>
8#include <elf.h>
9#include <byteswap.h>
10#define USE_BSD
11#include <endian.h>
12#include <regex.h>
13
14static void die(char *fmt, ...);
15
16#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
17static Elf32_Ehdr ehdr;
18static unsigned long reloc_count, reloc_idx;
19static unsigned long *relocs;
20
21struct section {
22 Elf32_Shdr shdr;
23 struct section *link;
24 Elf32_Sym *symtab;
25 Elf32_Rel *reltab;
26 char *strtab;
27};
28static struct section *secs;
29
30/*
31 * Following symbols have been audited. There values are constant and do
32 * not change if bzImage is loaded at a different physical address than
33 * the address for which it has been compiled. Don't warn user about
34 * absolute relocations present w.r.t these symbols.
35 */
36static const char abs_sym_regex[] =
37 "^(xen_irq_disable_direct_reloc$|"
38 "xen_save_fl_direct_reloc$|"
39 "VDSO|"
40 "__crc_)";
41static regex_t abs_sym_regex_c;
42static int is_abs_reloc(const char *sym_name)
43{
44 return !regexec(&abs_sym_regex_c, sym_name, 0, NULL, 0);
45}
46
47/*
48 * These symbols are known to be relative, even if the linker marks them
49 * as absolute (typically defined outside any section in the linker script.)
50 */
51static const char rel_sym_regex[] =
52 "^_end$";
53static regex_t rel_sym_regex_c;
54static int is_rel_reloc(const char *sym_name)
55{
56 return !regexec(&rel_sym_regex_c, sym_name, 0, NULL, 0);
57}
58
59static void regex_init(void)
60{
61 char errbuf[128];
62 int err;
63
64 err = regcomp(&abs_sym_regex_c, abs_sym_regex,
65 REG_EXTENDED|REG_NOSUB);
66 if (err) {
67 regerror(err, &abs_sym_regex_c, errbuf, sizeof errbuf);
68 die("%s", errbuf);
69 }
70
71 err = regcomp(&rel_sym_regex_c, rel_sym_regex,
72 REG_EXTENDED|REG_NOSUB);
73 if (err) {
74 regerror(err, &rel_sym_regex_c, errbuf, sizeof errbuf);
75 die("%s", errbuf);
76 }
77}
78
79static void die(char *fmt, ...)
80{
81 va_list ap;
82 va_start(ap, fmt);
83 vfprintf(stderr, fmt, ap);
84 va_end(ap);
85 exit(1);
86}
87
88static const char *sym_type(unsigned type)
89{
90 static const char *type_name[] = {
91#define SYM_TYPE(X) [X] = #X
92 SYM_TYPE(STT_NOTYPE),
93 SYM_TYPE(STT_OBJECT),
94 SYM_TYPE(STT_FUNC),
95 SYM_TYPE(STT_SECTION),
96 SYM_TYPE(STT_FILE),
97 SYM_TYPE(STT_COMMON),
98 SYM_TYPE(STT_TLS),
99#undef SYM_TYPE
100 };
101 const char *name = "unknown sym type name";
102 if (type < ARRAY_SIZE(type_name)) {
103 name = type_name[type];
104 }
105 return name;
106}
107
108static const char *sym_bind(unsigned bind)
109{
110 static const char *bind_name[] = {
111#define SYM_BIND(X) [X] = #X
112 SYM_BIND(STB_LOCAL),
113 SYM_BIND(STB_GLOBAL),
114 SYM_BIND(STB_WEAK),
115#undef SYM_BIND
116 };
117 const char *name = "unknown sym bind name";
118 if (bind < ARRAY_SIZE(bind_name)) {
119 name = bind_name[bind];
120 }
121 return name;
122}
123
124static const char *sym_visibility(unsigned visibility)
125{
126 static const char *visibility_name[] = {
127#define SYM_VISIBILITY(X) [X] = #X
128 SYM_VISIBILITY(STV_DEFAULT),
129 SYM_VISIBILITY(STV_INTERNAL),
130 SYM_VISIBILITY(STV_HIDDEN),
131 SYM_VISIBILITY(STV_PROTECTED),
132#undef SYM_VISIBILITY
133 };
134 const char *name = "unknown sym visibility name";
135 if (visibility < ARRAY_SIZE(visibility_name)) {
136 name = visibility_name[visibility];
137 }
138 return name;
139}
140
141static const char *rel_type(unsigned type)
142{
143 static const char *type_name[] = {
144#define REL_TYPE(X) [X] = #X
145 REL_TYPE(R_386_NONE),
146 REL_TYPE(R_386_32),
147 REL_TYPE(R_386_PC32),
148 REL_TYPE(R_386_GOT32),
149 REL_TYPE(R_386_PLT32),
150 REL_TYPE(R_386_COPY),
151 REL_TYPE(R_386_GLOB_DAT),
152 REL_TYPE(R_386_JMP_SLOT),
153 REL_TYPE(R_386_RELATIVE),
154 REL_TYPE(R_386_GOTOFF),
155 REL_TYPE(R_386_GOTPC),
156#undef REL_TYPE
157 };
158 const char *name = "unknown type rel type name";
159 if (type < ARRAY_SIZE(type_name) && type_name[type]) {
160 name = type_name[type];
161 }
162 return name;
163}
164
165static const char *sec_name(unsigned shndx)
166{
167 const char *sec_strtab;
168 const char *name;
169 sec_strtab = secs[ehdr.e_shstrndx].strtab;
170 name = "<noname>";
171 if (shndx < ehdr.e_shnum) {
172 name = sec_strtab + secs[shndx].shdr.sh_name;
173 }
174 else if (shndx == SHN_ABS) {
175 name = "ABSOLUTE";
176 }
177 else if (shndx == SHN_COMMON) {
178 name = "COMMON";
179 }
180 return name;
181}
182
183static const char *sym_name(const char *sym_strtab, Elf32_Sym *sym)
184{
185 const char *name;
186 name = "<noname>";
187 if (sym->st_name) {
188 name = sym_strtab + sym->st_name;
189 }
190 else {
191 name = sec_name(secs[sym->st_shndx].shdr.sh_name);
192 }
193 return name;
194}
195
196
197
198#if BYTE_ORDER == LITTLE_ENDIAN
199#define le16_to_cpu(val) (val)
200#define le32_to_cpu(val) (val)
201#endif
202#if BYTE_ORDER == BIG_ENDIAN
203#define le16_to_cpu(val) bswap_16(val)
204#define le32_to_cpu(val) bswap_32(val)
205#endif
206
207static uint16_t elf16_to_cpu(uint16_t val)
208{
209 return le16_to_cpu(val);
210}
211
212static uint32_t elf32_to_cpu(uint32_t val)
213{
214 return le32_to_cpu(val);
215}