00001 /*********************************************************** 00002 *PANALIX 0.06, (c) Adrian Panasiuk 2002-4 * 00003 *adek336[at]o2.pl, panalix.prv.pl * 00004 *under GPLv3 license * 00005 * * 00006 *panalix - small osdev project * 00007 ************************************************************ 00008 * elf.cpp, version 1.3 * 00009 ************************************************************ 00010 * * 00011 *some support for the executable and linkable format. * 00012 * * 00013 *30'05'04- forked from the old 0.o5 branch (1.3) * 00014 * * 00015 ***********************************************************/ 00016 00017 #include "src/common/shared.hpp" 00018 #include "src/common/blist.hpp" 00019 #include "src/tty/teletype.hpp" 00020 #include "src/memory/heap.hpp" 00021 #include "src/memory/memset.hpp" 00022 #include "src/module/elf.hpp" 00023 // #include "LINKER/cpprtl.hpp" 00024 // #include "LINKER/teletype.hpp" 00025 // #include "LINKER/debug.hpp" 00026 // #include "LINKER/MM/memheap.hpp" 00027 // #include "LINKER/linker.hpp" 00028 // #include "LINKER/blist.hpp" 00029 // #include "LINKER/MODS/syms.hpp" 00030 // #include "LINKER/MODS/elf.hpp" 00031 00032 00033 /*=======================================CLASS MANAGEMENT===================================*/ 00034 // /*init*/ 00035 // elf_t::elf_t() 00036 // { 00037 // /*there's no image at the moment*/ 00038 // image = (char*) NULL; 00039 // ehdr = (Elf32_ehdr*) NULL; 00040 // size = 0; 00041 // valid = 0; 00042 // } 00043 // 00044 // /*init and set ptr to data*/ 00045 // elf_t::elf_t(char *ptr, uint32 sze) 00046 // { 00047 // /*init*/ 00048 // set(ptr, sze); 00049 // } 00050 00051 /*init and set ptr to data*/ 00052 void elf_t::init(char *ptr, uint32 sze) 00053 { 00054 /*set the info about the image*/ 00055 image = ptr; 00056 size = sze; 00057 ehdr = (Elf32_ehdr*) image; 00058 00059 /*check validity*/ 00060 valid = ident(); 00061 } 00062 00063 /*set custom ehdr*/ 00064 void elf_t::set_ehdr(Elf32_ehdr *_ehdr, uint32 sze) 00065 { 00066 /* clear */ 00067 memset(this,0,sizeof(elf_t)); 00068 /*just set the ehdr variable*/ 00069 ehdr = _ehdr; 00070 size = sze; 00071 00072 /*check validity*/ 00073 valid = ident(); 00074 } 00075 00076 // /*done.*/ 00077 // elf_t::~elf_t() 00078 // { 00079 // /*done*/ 00080 // done(); 00081 // } 00082 00083 /*done.*/ 00084 void elf_t::done() { 00085 memset(this,0,sizeof(elf_t)); 00086 } 00087 00088 /*check elf validity*/ 00089 char elf_t::ident() 00090 { 00091 const uint32 NON_VALID = 0; 00092 const uint32 VALID = 1; 00093 00094 /*check for size - if is smaller than a full ehdr, it is nonvalid*/ 00095 if (size < sizeof(Elf32_ehdr)) return NON_VALID; 00096 00097 /*check magic key for 'ELF'*/ 00098 if (ehdr -> e_ident[0] != 0x7F) return NON_VALID; 00099 if (ehdr -> e_ident[1] != 'E' ) return NON_VALID; 00100 if (ehdr -> e_ident[2] != 'L' ) return NON_VALID; 00101 if (ehdr -> e_ident[3] != 'F' ) return NON_VALID; 00102 00103 /*check architecture*/ 00104 if (ehdr -> e_machine != EM_386) return NON_VALID; 00105 00106 /*check class for ELFCLASS32*/ 00107 if (ehdr -> e_ident[EI_CLASS] != ELFCLASS32) return NON_VALID; 00108 00109 /*check endianness for ELFDATA2LSB*/ 00110 if (ehdr -> e_ident[EI_DATA] != ELFDATA2LSB) return NON_VALID; 00111 00112 /*check elf header version*/ 00113 if (ehdr -> e_ident[EI_VERSION] != EV_CURRENT) return NON_VALID; 00114 if (ehdr -> e_version != EV_CURRENT) return NON_VALID; 00115 00116 00117 /*if the image passed all those tests, the image is a valid 00118 Executable and Linkable Format module.*/ 00119 return VALID; 00120 } 00121 00122 /*========================================DATA TYPES=======================================*/ 00123 00124 /*returns pointer to a section header, if exists*/ 00125 Elf32_shdr *elf_t::section(uint32 n) 00126 { 00127 /*check validity*/ 00128 if (valid == 0) return (Elf32_shdr*) NULL; 00129 00130 /*check if such a section exists*/ 00131 if (ehdr->e_shnum <= n) return (Elf32_shdr*) NULL; 00132 00133 /*return the pointer*/ 00134 return (Elf32_shdr*) 00135 ((uint32) image + /*the image's start point*/ 00136 ehdr->e_shoff + /*the start of the section header table (relocatable)*/ 00137 ehdr->e_shentsize * n); /*the offset of the section header in the table*/ 00138 } 00139 00140 /*returns pointer to a section, if exists*/ 00141 void *elf_t::sect_addr(uint32 n) 00142 { 00143 Elf32_shdr *s = section(n); 00144 uint32 ret; 00145 /*check validity*/ 00146 if (!s) 00147 return NULL; 00148 /*check module type*/ 00149 if (ehdr->e_type == ET_REL) 00150 ret = ((uint32)image+ /*image in memory*/ 00151 s->sh_offset); /*section offset (relocatables)*/ 00152 else 00153 ret = ((uint32)image+ /*image in memory*/ 00154 s->sh_addr); /*section offset (executables)*/ 00155 00156 /*return*/ 00157 return (void*)ret; 00158 } 00159 00160 /*returns pointer to a program header, if exists*/ 00161 Elf32_phdr *elf_t::segment(uint32 n) 00162 { 00163 /*check validity*/ 00164 if (valid == 0) return NULL; 00165 00166 /*check if such a segment exists*/ 00167 if (ehdr->e_phnum <= n) return NULL; 00168 00169 /*return the pointer*/ 00170 return (Elf32_phdr*) 00171 ((uint32) image + /*the image's start point*/ 00172 ehdr->e_phoff + /*the start of the program header table*/ 00173 ehdr->e_phentsize * n); /*the offset of the program header in the table*/ 00174 } 00175 00176 /*returns pointer to a segment, if exists*/ 00177 void *elf_t::segm_addr(uint32 n) 00178 { 00179 Elf32_phdr *segm = segment(n); 00180 if (segm == NULL) 00181 return NULL; 00182 00183 return (void*) ((uint32) image + segm->p_offset); 00184 } 00185 00186 /*returns pointer to a symtab entry #n in section sect*/ 00187 Elf32_sym *elf_t::symbol(uint32 sect, uint32 n) 00188 { 00189 Elf32_shdr *sc; 00190 sc = section(sect); 00191 00192 /*check if such a section exists. image validity tested by section()*/ 00193 if (sc == 0) return 0; 00194 00195 /*check symtab section type*/ 00196 if (sc -> sh_type != SHT_SYMTAB) return 0; 00197 00198 /*check symtab section size*/ 00199 if (n >= sc -> sh_size / sc->sh_entsize) return 0; 00200 00201 /*return a pointer*/ 00202 return (Elf32_sym*) ((uint32) sect_addr(sect) + sc->sh_entsize * n); 00203 // return (Elf32_sym*)((uint32)image + /*pointer to image*/ 00204 // sc -> sh_offset + /*offset of symtab in image*/ 00205 // sc -> sh_entsize * n);/*offset of symbol in table*/ 00206 } 00207 00208 /*returns a pointer to a strtab entry with offset off in section sect*/ 00209 char *elf_t::str(uint32 sect, uint32 off) 00210 { 00211 Elf32_shdr *sc; 00212 sc = section(sect); 00213 00214 /*check if such a section exists. image validity tested by section()*/ 00215 if (sc == 0) return 0; 00216 00217 /*check strtab section type*/ 00218 if (sc -> sh_type != SHT_STRTAB) return 0; 00219 00220 /*check symtab section size*/ 00221 if (off >= sc -> sh_size) return 0; 00222 00223 /*return a pointer*/ 00224 return off + (char*) sect_addr(sect); 00225 // return (char*)((uint32)image + /*pointer to image*/ 00226 // sc -> sh_offset + /*offset of strtab in image*/ 00227 // off); /*offset of string in table*/ 00228 } 00229 00230 /*returns a pointer to a rel/rela section entry #n in section sect*/ 00231 Elf32_reloc *elf_t::reloc(uint32 sect, uint32 n) 00232 { 00233 Elf32_shdr *sc; 00234 sc = section(sect); 00235 00236 /*check if such a section exists. image validity tested by section()*/ 00237 if (sc == 0) return 0; 00238 00239 /*check rel/rela section type*/ 00240 if (sc -> sh_type != SHT_REL) 00241 if (sc -> sh_type != SHT_RELA) 00242 return 0; 00243 00244 /*check section size*/ 00245 if (n >= sc -> sh_size / sc -> sh_entsize) return 0; 00246 00247 /*return a pointer*/ 00248 return (Elf32_reloc*)((uint32)image + /*pointer to image*/ 00249 sc -> sh_offset + /*offset of section in image*/ 00250 sc->sh_entsize * n);/*offset of string in table*/ 00251 } 00252 // /* 00253 // uint32 xyz; 00254 // /*===========================================SYMS==========================================*/ 00255 // /*saves all defined/undefined (defined == [0;1]) symbols with bind_type == sym_bind from this elf to list*/ 00256 // uint32 elf_t::save_syms(blist_t *list, uint32 sym_bind, uint32 defined, mod_t *mod) 00257 // { 00258 // uint32 i, n, val; 00259 // Elf32_shdr *sect; 00260 // Elf32_sym *sym; 00261 // char *ch; 00262 // xyz++; 00263 // /*find the symbol sections*/ 00264 // for (i=0; i<ehdr->e_shnum; i++) 00265 // { 00266 // sect = (Elf32_shdr*)((uint32) ehdr->e_shoff + i * ehdr->e_shentsize + (uint32) image); 00267 // /*check type*/ 00268 // if (sect -> sh_type != SHT_SYMTAB) 00269 // continue; 00270 // 00271 // /*get each symbol*/ 00272 // for (n=0; n < sect -> sh_size / (sect -> sh_entsize); n++) 00273 // { 00274 // /*every 0x28 symbols put a dot*/ 00275 // if (n - ((n / 0x28) * 0x28) == 0x28 - 1) 00276 // kprintf("."); 00277 // /*the symtab entry analysed*/ 00278 // sym = (Elf32_sym*)(n * sect -> sh_entsize + (uint32)image); 00279 // 00280 // /*whether relocatable/linkable; either sh_addr or sh_offset*/ 00281 // if (ehdr->e_type == ET_EXEC) 00282 // sym = (Elf32_sym*) ((uint32)sym + sect -> sh_addr); /*executable*/ 00283 // else 00284 // sym = (Elf32_sym*) ((uint32)sym + sect -> sh_offset);/*relocatable*/ 00285 // 00286 // /*add only defined global symbols to the kernel_syms table*/ 00287 // if ((defined) ^ (sym -> st_shndx == SHN_UNDEF)) 00288 // if ((uint32)(sym -> st_info >> 4) == sym_bind) 00289 // { 00290 // /*the symbol name*/ 00291 // ch = (char*) ((Elf32_shdr*) ((uint32) image + (uint32) ehdr->e_shoff + sect -> sh_link * ehdr->e_shentsize)); 00292 // if (ehdr->e_type == ET_EXEC) 00293 // ch = (char*)(((Elf32_shdr*) ch) -> sh_addr); /*executable*/ 00294 // else 00295 // ch = (char*)(((Elf32_shdr*) ch) -> sh_offset); /*relocatable*/ 00296 // ch = (char*)((uint32)ch + sym->st_name + (uint32) image); 00297 // /*the symbol value*/ 00298 // val = sym -> st_value; 00299 // /*the symbol's address may need to be fixed by the section's addr in memory for reloc modules*/ 00300 // if (ehdr -> e_type == ET_REL) 00301 // val+=(uint32)sect_addr(sym->st_shndx); 00302 // /*add to list*/ 00303 // add_sym(list, ch, val, mod, sym, sect); 00304 // } 00305 // } 00306 // } 00307 // 00308 // /*return success*/ 00309 // return DEF_SUCCESS; 00310 // } 00311 // 00312 // /*perform relocations indicitated by rel/rela sections*/ 00313 // void elf_t::relocate() 00314 // { 00315 // uint32 i, n; 00316 // Elf32_shdr *sect; 00317 // Elf32_reloc *reloc; 00318 // 00319 // /*check validity*/ 00320 // if (!valid) 00321 // return; 00322 // 00323 // /*check each section*/ 00324 // for (i=0; i<ehdr->e_shnum;i++) 00325 // { 00326 // /*get section addr*/ 00327 // sect = section(i); 00328 // /*check if is a reloc section*/ 00329 // if (sect -> sh_type != SHT_REL) 00330 // if (sect -> sh_type != SHT_RELA) 00331 // continue; 00332 // /*check each reltab entry*/ 00333 // for (n=0; n<(sect -> sh_size) / (sect -> sh_entsize); n++) 00334 // { 00335 // /*relocation entry*/ 00336 // reloc = (Elf32_reloc*) ((uint32)sect_addr(i) + n * sect -> sh_entsize); 00337 // /*now, relocate entry*/ 00338 // do_elf_reloc(reloc, sect); 00339 // } 00340 // } 00341 // } 00342 // 00343 // /*perform relocations indicitated by rel/rela sections for symtab entry sym*/ 00344 // void elf_t::un_reloc(Elf32_sym *sym) 00345 // { 00346 // uint32 i, n; 00347 // Elf32_shdr *sect; 00348 // Elf32_reloc *reloc; 00349 // Elf32_shdr *symtab; 00350 // Elf32_sym *symb; 00351 // 00352 // /*check validity*/ 00353 // if (!valid) 00354 // return; 00355 // 00356 // /*check each section*/ 00357 // for (i=0; i<ehdr->e_shnum;i++) 00358 // { 00359 // /*get section addr*/ 00360 // sect = section(i); 00361 // /*check if is a reloc section*/ 00362 // if (sect -> sh_type != SHT_REL) 00363 // if (sect -> sh_type != SHT_RELA) 00364 // continue; 00365 // /*check each reltab entry*/ 00366 // for (n=0; n<(sect -> sh_size) / (sect -> sh_entsize); n++) 00367 // { 00368 // /*relocation entry*/ 00369 // reloc = (Elf32_reloc*) ((uint32)sect_addr(i) + n * sect -> sh_entsize); 00370 // /*the symtab connected with the relocation entry*/ 00371 // symtab = section(sect -> sh_link); 00372 // /*and the appropriate symtab entry*/ 00373 // symb = (Elf32_sym*)( 00374 // (uint32) sect_addr(sect->sh_link)+ 00375 // symtab -> sh_entsize * reloc -> r_symtabndx);/*entry #(reloc->r_symtabndx) in the table*/ 00376 // /*check if this is the sym*/ 00377 // if (symb != sym) 00378 // continue; 00379 // 00380 // /*now, unreloc entry*/ 00381 // undo_elf_reloc(reloc, sect); 00382 // } 00383 // } 00384 // } 00385 // 00386 // /*perform relocations indicitated by rel/rela sections for symtab entry sym*/ 00387 // void elf_t::relocate(Elf32_sym *sym) 00388 // { 00389 // uint32 i, n; 00390 // Elf32_shdr *sect; 00391 // Elf32_reloc *reloc; 00392 // Elf32_shdr *symtab; 00393 // Elf32_sym *symb; 00394 // 00395 // /*check validity*/ 00396 // if (!valid) 00397 // return; 00398 // 00399 // /*check each section*/ 00400 // for (i=0; i<ehdr->e_shnum;i++) 00401 // { 00402 // /*get section addr*/ 00403 // sect = section(i); 00404 // /*check if is a reloc section*/ 00405 // if (sect -> sh_type != SHT_REL) 00406 // if (sect -> sh_type != SHT_RELA) 00407 // continue; 00408 // /*check each reltab entry*/ 00409 // for (n=0; n<(sect -> sh_size) / (sect -> sh_entsize); n++) 00410 // { 00411 // /*relocation entry*/ 00412 // reloc = (Elf32_reloc*) ((uint32)sect_addr(i) + n * sect -> sh_entsize); 00413 // /*the symtab connected with the relocation entry*/ 00414 // symtab = section(sect -> sh_link); 00415 // /*and the appropriate symtab entry*/ 00416 // symb = (Elf32_sym*)( 00417 // (uint32) sect_addr(sect->sh_link)+ 00418 // symtab -> sh_entsize * reloc -> r_symtabndx);/*entry #(reloc->r_symtabndx) in the table*/ 00419 // /*check if this is the sym*/ 00420 // if (symb != sym) 00421 // continue; 00422 // 00423 // /*now, unreloc entry*/ 00424 // do_elf_reloc(reloc, sect); 00425 // } 00426 // } 00427 // } 00428 // 00429 // /*perform single relocation*/ 00430 // void elf_t::do_elf_reloc(Elf32_reloc *reloc, Elf32_shdr *sect) 00431 // { 00432 // uint32 *relocated_element; 00433 // uint32 addend; 00434 // Elf32_shdr *symtab; 00435 // Elf32_sym *sym; 00436 // 00437 // /*the symtab connected with the relocation entry*/ 00438 // symtab = section(sect -> sh_link); 00439 // /*and the appropriate symtab entry*/ 00440 // sym = (Elf32_sym*)( 00441 // (uint32) sect_addr(sect->sh_link)+ 00442 // symtab -> sh_entsize * reloc -> r_symtabndx);/*entry #(reloc->r_symtabndx) in the table*/ 00443 // 00444 // /*create a pointer to the relocated object*/ 00445 // relocated_element = (uint32*) ( 00446 // (uint32) sect_addr(sect->sh_info) + 00447 // reloc->r_addr); /*offset in the section*/ 00448 // 00449 // /*save the addend's value which depends on section type*/ 00450 // if (sect -> sh_type == SHT_REL) 00451 // addend = *relocated_element; /*the addend's already there*/ 00452 // else /*RELA*/ 00453 // addend = reloc -> r_addend; 00454 // 00455 // /*all freshly bound symbols have SHN_UNDEF st_shndx so we can adjust the symbol value*/ 00456 // if (sym ->st_shndx == SHN_UNDEF) 00457 // { 00458 // sym -> st_value -= (uint32) relocated_element - reloc->r_addr; 00459 // /*we should not fix the value twice, if it was referenced twice*/ 00460 // sym -> st_shndx = sect -> sh_info; 00461 // } 00462 // 00463 // /*now relocate the element. check the relocation type*/ 00464 // switch (reloc -> r_type) 00465 // { 00466 // /*S + A*/ 00467 // case R_386_32: 00468 // *relocated_element = 00469 // addend + /* +Addend*/ 00470 // sym -> st_value + /* +Value*/ 00471 // (uint32) sect_addr(sect->sh_info);/* +the section's address in memory (aka the rest of the Value)*/ 00472 // /*check if the symbol's section is the same as the relocated section. 00473 // if not, we have to fix the element with the difference*/ 00474 // *relocated_element-= 00475 // (uint32)sect_addr(sect->sh_info) - /*the relocated section*/ 00476 // (uint32)sect_addr(sym->st_shndx); /*the symbol's section*/ 00477 // break; 00478 // /*S + A - P*/ 00479 // case R_386_PC32: 00480 // *relocated_element = 00481 // addend + /* +Addend*/ 00482 // sym -> st_value - /* +Value*/ 00483 // reloc->r_addr; /* -Position*/ 00484 // break; 00485 // }; 00486 // } 00487 // 00488 // /*delete old relocation*/ 00489 // void elf_t::undo_elf_reloc(Elf32_reloc *reloc, Elf32_shdr *sect) 00490 // { 00491 // uint32 *relocated_element; 00492 // Elf32_shdr *symtab; 00493 // Elf32_sym *sym; 00494 // 00495 // /*the symtab connected with the relocation entry*/ 00496 // symtab = section(sect -> sh_link); 00497 // /*and the appropriate symtab entry*/ 00498 // sym = (Elf32_sym*)( 00499 // (uint32) sect_addr(sect->sh_link)+ 00500 // symtab -> sh_entsize * reloc -> r_symtabndx);/*entry #(reloc->r_symtabndx) in the table*/ 00501 // 00502 // /*create a pointer to the relocated object*/ 00503 // relocated_element = (uint32*) ( 00504 // (uint32) sect_addr(sect->sh_info) + 00505 // reloc->r_addr); /*offset in the section*/ 00506 // 00507 // /*all freshly bound symbols have SHN_UNDEF st_shndx so we can adjust the symbol value*/ 00508 // if (sym ->st_shndx == SHN_UNDEF) 00509 // { 00510 // sym -> st_value -= (uint32) relocated_element - reloc->r_addr; 00511 // /*we should not fix the value twice, if it was referenced twice*/ 00512 // sym -> st_shndx = sect -> sh_info; 00513 // } 00514 // 00515 // /*now un-relocate the element. check the relocation type. after this *relocated_element will be equal to the addend*/ 00516 // switch (reloc -> r_type) 00517 // { 00518 // /*S + A*/ 00519 // case R_386_32: 00520 // *relocated_element = 00521 // *relocated_element - 00522 // sym -> st_value - /* +Value*/ 00523 // (uint32) sect_addr(sect->sh_info);/* +the section's address in memory (aka the rest of the Value)*/ 00524 // /*check if the symbol's section is the same as the relocated section. 00525 // if not, we have to fix the element with the difference*/ 00526 // *relocated_element+= 00527 // (uint32)sect_addr(sect->sh_info) - /*the relocated section*/ 00528 // (uint32)sect_addr(sym->st_shndx); /*the symbol's section*/ 00529 // break; 00530 // /*S + A - P*/ 00531 // case R_386_PC32: 00532 // *relocated_element = 00533 // *relocated_element - 00534 // sym -> st_value + /* +Value*/ 00535 // reloc->r_addr; /* -Position*/ 00536 // break; 00537 // }; 00538 // }*/ 00539 00540 /*===========================================MISC==========================================*/ 00541 /*create a header*/ 00542 int create_ehdr(Elf32_ehdr *ehdr, uint32 shnum, 00543 Elf32_shdr *shaddr, uint32 shentsize, uint32 shstrndx, uint32 e_type) 00544 { 00545 /*put identification data*/ 00546 /*magic*/ 00547 ehdr -> e_ident[0] = 0x7F; 00548 ehdr -> e_ident[1] = 'E'; 00549 ehdr -> e_ident[2] = 'L'; 00550 ehdr -> e_ident[3] = 'F'; 00551 /*architecture*/ 00552 ehdr -> e_machine = EM_386; 00553 /*class for ELFCLASS32*/ 00554 ehdr -> e_ident[EI_CLASS] = ELFCLASS32; 00555 /*endianness for ELFDATA2LSB*/ 00556 ehdr -> e_ident[EI_DATA] = ELFDATA2LSB; 00557 /*elf header version*/ 00558 ehdr -> e_ident[EI_VERSION] = EV_CURRENT; 00559 ehdr -> e_version = EV_CURRENT; 00560 00561 /*fill in custom data*/ 00562 ehdr->e_shnum = shnum; /*section header count*/ 00563 ehdr->e_shoff = (uint32) shaddr; /*offset of section header*/ 00564 ehdr->e_shentsize = shentsize; /*shentry size*/ 00565 ehdr->e_shstrndx = shstrndx; /*strtab for section names*/ 00566 ehdr->e_type = e_type; /*file type*/ 00567 00568 /*return value*/ 00569 return ESUCCESS; 00570 } 00571 00572 /*********************************************************** 00573 * * 00574 *panalix 0.06 (c) Adrian Panasiuk 2002-4 * 00575 *adek336[at]o2.pl, panalix.prv.pl * 00576 * * 00577 ***********************************************************/