40 #include "loader/elf32.h"
41 #include "loader/cle.h"
42 #include "loader/sym.h"
45 #include "lib/assert.h"
48 #define PRINTF(...) do {} while (0)
50 #define PRINTF(...) printf(__VA_ARGS__)
70 cle_read_info(
struct cle_info *info,
71 int (*pread)(
void *,
int, off_t),
80 struct elf32_ehdr ehdr;
81 struct elf32_shdr shdr;
83 #define ehdr huge.ehdr
84 #define shdr huge.shdr
90 cle_word strtabsize = 0;
93 memset(info, 0x0,
sizeof(*info));
95 ret = pread(&ehdr,
sizeof(ehdr), hdr);
99 if(memcmp(ehdr.e_ident, ELF_MAGIC_HEADER, ELF_MAGIC_HEADER_SIZE) != 0) {
100 return CLE_BAD_HEADER;
103 shoff = hdr + ehdr.e_shoff;
104 shentsize = ehdr.e_shentsize;
105 shnum = ehdr.e_shnum;
108 ret = pread(&shdr,
sizeof(shdr), shoff + shentsize*ehdr.e_shstrndx);
118 strs = shdr.sh_offset;
134 for(i = 0; i < shnum; ++i) {
135 ret = pread(&shdr,
sizeof(shdr), shoff);
139 ret = pread(info->name,
sizeof(info->name), hdr + strs + shdr.sh_name);
142 if(strncmp(info->name,
".text", 5) == 0) {
143 info->textoff = shdr.sh_offset;
144 info->textsize = shdr.sh_size;
145 info->text_shndx = i;
146 }
else if(strncmp(info->name,
".rela.text", 10) == 0) {
147 info->textrelaoff = shdr.sh_offset;
148 info->textrelasize = shdr.sh_size;
149 }
else if(strncmp(info->name,
".data", 5) == 0) {
150 info->dataoff = shdr.sh_offset;
151 info->datasize = shdr.sh_size;
152 info->data_shndx = i;
153 }
else if(strncmp(info->name,
".rela.data", 10) == 0) {
154 info->datarelaoff = shdr.sh_offset;
155 info->datarelasize = shdr.sh_size;
156 }
else if(strncmp(info->name,
".symtab", 7) == 0) {
157 info->symtaboff = shdr.sh_offset;
158 info->symtabsize = shdr.sh_size;
159 }
else if(strncmp(info->name,
".strtab", 7) == 0) {
160 info->strtaboff = shdr.sh_offset;
161 strtabsize = shdr.sh_size;
162 }
else if(strncmp(info->name,
".bss", 4) == 0) {
163 info->bsssize = shdr.sh_size;
166 info->name[
sizeof(info->name) - 1] = 0;
167 PRINTF(
"cle: unknown section %.12s\n", info->name);
174 if(info->symtabsize == 0) {
175 return CLE_NO_SYMTAB;
177 if(strtabsize == 0) {
178 return CLE_NO_STRTAB;
180 if(info->textsize == 0) {
196 cle_relocate(
struct cle_info *info,
197 int (*pread)(
void *,
int, off_t),
203 struct elf32_rela rela;
209 for(off = hdr + reloff;
210 off < hdr + reloff + relsize;
211 off +=
sizeof(
struct elf32_rela)) {
212 ret = pread(&rela,
sizeof(rela), off);
214 ret = pread(&s,
sizeof(s),
215 hdr + info->symtaboff
216 +
sizeof(
struct elf32_sym)*ELF32_R_SYM(rela.r_info));
219 if(s.st_shndx == info->bss_shndx) {
220 addr = (cle_addr)(uintptr_t)info->bss;
221 }
else if(s.st_shndx == info->data_shndx) {
222 addr = (cle_addr)(uintptr_t)info->data;
223 }
else if(s.st_shndx == info->text_shndx) {
231 return CLE_UNKNOWN_SEGMENT;
234 ret = pread(info->name,
sizeof(info->name),
235 hdr + info->strtaboff + s.st_name);
237 cle_addr sym = (cle_addr)(uintptr_t)sym_function(info->name);
243 sym = (cle_addr)(uintptr_t)sym_object(info->name);
245 if(addr == NOLL && sym != NOLL) {
247 }
else if(addr != NOLL && sym == NOLL) {
248 addr = addr + s.st_value;
249 }
else if(addr == NOLL && sym == NOLL) {
250 PRINTF(
"cle: undefined reference to %.32s (%d)\n",
251 info->name, s.st_info);
252 return CLE_UNDEFINED;
253 }
else if(addr != NOLL && sym != NOLL) {
254 PRINTF(
"cle: multiple definitions of %.32s (%d)\n",
255 info->name, s.st_info);
256 return CLE_MULTIPLY_DEFINED;
260 addr += rela.r_addend;
262 ret = cle_write_reloc(segmem + rela.r_offset, &rela, addr, info);
276 cle_lookup(
struct cle_info *info,
277 int (*pread)(
void *,
int, off_t),
287 for(a = hdr + info->symtaboff;
288 a < hdr + info->symtaboff + info->symtabsize;
290 ret = pread(&s,
sizeof(s), a);
294 ret = pread(info->name,
sizeof(info->name),
295 hdr + info->strtaboff + s.st_name);
298 if(strcmp(info->name, symbol) == 0) {
299 if(s.st_shndx == info->bss_shndx) {
300 addr = (cle_addr)(uintptr_t)info->bss;
301 }
else if(s.st_shndx == info->data_shndx) {
302 addr = (cle_addr)(uintptr_t)info->data;
303 }
else if(s.st_shndx == info->text_shndx) {
306 return (
void *)(uintptr_t)((addr + s.st_value) >> 1);
312 return (
void *)(uintptr_t)(addr + s.st_value);
#define NULL
The null pointer.