Annotation of dietlibc/ldso.c, revision 1.1
1.1 ! leitner 1: #define errno fnord
! 2: #include <unistd.h>
! 3: #include <fcntl.h>
! 4: #include <sys/mman.h>
! 5: #include <elf.h>
! 6: #include <stdlib.h>
! 7: #include <stdint.h>
! 8: #undef errno
! 9:
! 10: #if (__WORDSIZE == 64)
! 11:
! 12: #define phdr Elf64_Phdr
! 13: #define ehdr Elf64_Ehdr
! 14: #define shdr Elf64_Shdr
! 15: #define sym Elf64_Sym
! 16: #define dyn Elf64_Dyn
! 17:
! 18: #else
! 19:
! 20: #define phdr Elf32_Phdr
! 21: #define ehdr Elf32_Ehdr
! 22: #define shdr Elf32_Shdr
! 23: #define sym Elf32_Sym
! 24: #define dyn Elf32_Dyn
! 25:
! 26: #endif
! 27:
! 28: static int errno;
! 29: __attribute__((visibility("hidden"))) int* __errno_location(void) { return &errno; }
! 30:
! 31: static size_t _strlen(const char*s) {
! 32: size_t i;
! 33: for (i=0; s[i]; ++i);
! 34: return i;
! 35: }
! 36: static char* _stpcpy(char* dest,const char* src) {
! 37: size_t i;
! 38: for (i=0; src[i]; ++i)
! 39: dest[i]=src[i];
! 40: dest[i]=0;
! 41: return dest+i;
! 42: }
! 43: static char* _strchr(char* s,char c) {
! 44: size_t i;
! 45: for (i=0; s[i] && s[i]!=c; ++i) ;
! 46: if (s[i]==c) return s+i; else return NULL;
! 47: }
! 48: static int _strcmp(const void* str1,const void* str2) {
! 49: const unsigned char* a=str1;
! 50: const unsigned char* b=str2;
! 51: size_t i;
! 52: int r;
! 53: for (i=0; (r=(a[i]-b[i]))==0 && a[i]; ++i) ;
! 54: return r;
! 55: }
! 56: static int _memcmp(const void* dst,const void* src,size_t count) {
! 57: const unsigned char* a=dst;
! 58: const unsigned char* b=src;
! 59: size_t i;
! 60: int r;
! 61: for (i=0; i<count && (r=(a[i]-b[i]))==0; ++i) ;
! 62: return r;
! 63: }
! 64: static void* _memcpy(void* dst,const void* src,size_t len) {
! 65: char* a=dst;
! 66: const char* b=src;
! 67: size_t i;
! 68: for (i=0; i<len; ++i)
! 69: a[i]=b[i];
! 70: return dst;
! 71: }
! 72: static void _memset(void* dst,unsigned char c,size_t len) {
! 73: unsigned char* a=dst;
! 74: size_t i;
! 75: for (i=0; i<len; ++i) a[i]=c;
! 76: }
! 77: static ssize_t __write1(const char* s) {
! 78: write(1,s,_strlen(s));
! 79: }
! 80: static ssize_t __write2(const char* s) {
! 81: write(2,s,_strlen(s));
! 82: }
! 83:
! 84: ssize_t write(int fd,const void* buf,size_t len) __attribute__((visibility("hidden")));
! 85: int open(const char* pathname,int flags, ...) __attribute__((visibility("hidden")));
! 86: ssize_t read(int fd,void* buf,size_t len) __attribute__((visibility("hidden")));
! 87: int close(int fd) __attribute__((visibility("hidden")));
! 88: ssize_t pread64(int fd, void *buf, size_t count, off64_t offset) __attribute__((visibility("hidden")));;
! 89: void *mmap(void *__addr, size_t __len, int __prot, int __flags, int __fd, off_t __offset) __attribute__((visibility("hidden")));
! 90: int munmap(void *__addr, size_t __len) __attribute__((visibility("hidden")));
! 91: int mprotect (void *__addr, size_t __len, int __prot) __attribute__((visibility("hidden")));
! 92: void exit(int res) __attribute__((visibility("hidden")));
! 93:
! 94: static struct page {
! 95: struct page* next;
! 96: size_t a;
! 97: char data[4096-sizeof(size_t)-sizeof(struct page*)];
! 98: }* heap;
! 99:
! 100: static void* _malloc(size_t l) {
! 101: struct page** p;
! 102: if (l>sizeof(heap->data)) return 0;
! 103: if (l%(sizeof(void*)*2)) {
! 104: l += sizeof(void*)*2;
! 105: l -= l%(sizeof(void*)*2);
! 106: }
! 107: for (p=&heap; *p && (*p)->a<l; p=&((*p)->next)) ;
! 108: if (!*p) {
! 109: void* tmp=mmap(0,4096,PROT_READ|PROT_WRITE,MAP_ANONYMOUS|MAP_PRIVATE,-1,0);
! 110: if (tmp==MAP_FAILED) return 0;
! 111: *p=tmp;
! 112: (*p)->a=sizeof(heap->data);
! 113: }
! 114: if (l <= (*p)->a) {
! 115: char* tmp=(*p)->data+sizeof((*p)->data)-(*p)->a;
! 116: (*p)->a-=l;
! 117: return tmp;
! 118: } else
! 119: return 0; // can't happen
! 120: }
! 121:
! 122: static char path[100];
! 123: static char* ldlp;
! 124:
! 125: static struct dll {
! 126: struct dll* next;
! 127: ehdr* e;
! 128: shdr* s;
! 129: void* code,* data;
! 130: size_t codelen,datalen,codeplus;
! 131: char name[1]; // asciiz of library name
! 132: } *dlls, dllroot;
! 133:
! 134: static int map_sections(int fd,const ehdr* e,const phdr* p,struct dll* D) {
! 135: shdr* s;
! 136: size_t i;
! 137: uintptr_t codeplus=0;
! 138:
! 139: s=0;
! 140: for (i=0; i<e->e_phnum; ++i) {
! 141: if (p[i].p_type==PT_LOAD) {
! 142: size_t delta=p[i].p_offset%4096;
! 143: size_t maplen=p[i].p_filesz+delta;
! 144: size_t bssdiff=(p[i].p_filesz+delta)%4096;
! 145: char* c;
! 146: if ((p[i].p_flags&PF_W) && (p[i].p_flags&PF_X)) {
! 147: __write2("section is both executable and writable, aborting!\n");
! 148: return 1;
! 149: }
! 150: if (p[i].p_flags&PF_X) {
! 151: /* code segment */
! 152: size_t ofs,len,rolen=0,nolen=0,rolen2=0,vaddr=p[i].p_vaddr,baseofs=0;
! 153: /* the first segment will be the code segment, and it will have
! 154: * either a fixed address or 0 if it's a shared library. We
! 155: * insist that the mapping start at file offset 0, and we extend
! 156: * the mapping so it includes the section table */
! 157: ofs=p[i].p_offset;
! 158: len=p[i].p_filesz;
! 159: if (ofs) {
! 160: __write2("can't happen error: ofs!=0\n");
! 161: exit(1);
! 162: if (vaddr)
! 163: vaddr-=ofs;
! 164: else
! 165: baseofs=ofs;
! 166: rolen=ofs;
! 167: len+=ofs;
! 168: ofs=0;
! 169: }
! 170: if (ofs+len < e->e_shoff+e->e_shnum*e->e_shentsize) {
! 171: size_t needed=e->e_shoff+e->e_shnum*e->e_shentsize;
! 172: /* if this mapping does not include the section table is not
! 173: * included, extend the mapping to include it */
! 174: rolen2=e->e_shnum*e->e_shentsize;
! 175: if (rolen2>needed-len)
! 176: /* we were almost there, part of the section table was
! 177: * already mapped */
! 178: rolen2=needed-len;
! 179: else
! 180: nolen=needed-len-rolen2;
! 181: /*
! 182: * +------------------------+
! 183: * | rolen e-> | if the mapping did not start at beginning of file, this is the beginning of file, PROT_READ
! 184: * +------------------------+
! 185: * | len base-> | this is the actual mapping, base points here, PROT_READ|PROT_EXEC
! 186: * +------------------------+
! 187: * | nolen | stuff we don't really need and will mprotect PROT_NONE
! 188: * +------------------------+
! 189: * | rolen2 e+e->shoff | the section header table, PROT_READ
! 190: * +------------------------+
! 191: */
! 192: }
! 193: c=mmap((char*)vaddr,rolen+len+nolen+rolen2,
! 194: ((p[i].p_flags&PF_R)?PROT_READ:0) |
! 195: ((p[i].p_flags&PF_X)?PROT_EXEC:0),
! 196: MAP_SHARED|(vaddr?MAP_FIXED:0),
! 197: fd,0);
! 198: /* in case the can't happen branch ever happens */
! 199: D->e=(ehdr*)c;
! 200: D->code=c+rolen; D->codelen=len;
! 201: D->s=(shdr*)(c+e->e_shoff);
! 202: if (rolen>=4096) /* if we extended the mapping in the front, remove exec permissions */
! 203: mprotect(c,rolen&~4095,PROT_READ);
! 204: if (!vaddr) codeplus=(uintptr_t)(c+rolen);
! 205: if (nolen) {
! 206: /* We mapped junk in the middle.
! 207: * If there are full pages in there, map them PROT_NONE */
! 208: char* start=c+rolen+len;
! 209: size_t len=nolen;
! 210: size_t diff=(-(uintptr_t)start & 4095);
! 211: if (diff < nolen) {
! 212: /* diff is the part at the beginning we need to skip because
! 213: * it's on a page we actually need to be executable.
! 214: * Now find out if we overshoot onto a page we want */
! 215: size_t removeatend=((uintptr_t)c+rolen+len)&4095;
! 216: mprotect(start+diff,len-diff-removeatend,PROT_NONE);
! 217: }
! 218: }
! 219: if (rolen2) {
! 220: /* Now we want to mprotect PROT_READ the section table.
! 221: * What makes this complex is that mprotect granularity is one
! 222: * page. First figure out the region we are interested in. */
! 223: char* start=c+rolen+len+nolen;
! 224: size_t len=rolen2;
! 225: /* we want to mprotect from start to start+len */
! 226: int diff=((uintptr_t)start)&4095;
! 227: /* This is the offset of start from the page start. We need
! 228: * to mprotect the whole page -- unless it also has code on
! 229: * it, in which case we need to leave it alone */
! 230: if (diff > nolen) {
! 231: size_t roundup=(-(uintptr_t)start)&4095;
! 232: /* we need to skip the first page. Let's see if there is
! 233: * anything left in that case */
! 234: start+=roundup;
! 235: if (rolen2>roundup)
! 236: len-=roundup;
! 237: else
! 238: len=0;
! 239: } else {
! 240: start-=diff;
! 241: len+=diff;
! 242: }
! 243: if (len) mprotect(start,len,PROT_READ);
! 244: }
! 245: } else if (p[i].p_flags&PF_W) { /* data segment */
! 246: /* We have already mapped the code segment to base.
! 247: * For programs, the base mapping of the code and data segment
! 248: * is absolute and we just map there with MAP_FIXED. For shared
! 249: * libraries however, the base mapping of the code segment is 0,
! 250: * and the vaddr of the data segment is not absolute but
! 251: * relative to the code segment */
! 252:
! 253: /* The data segment may not start on a page boundary. Round
! 254: * start address if necessary. */
! 255: size_t addr,ofs,len,memsetstart=0,memsetend=0,additional=0;
! 256: addr=p[i].p_vaddr+codeplus;
! 257: ofs=p[i].p_offset;
! 258: len=p[i].p_filesz;
! 259: if ((memsetstart=(ofs%4096))) {
! 260: len+=memsetstart;
! 261: ofs-=memsetstart;
! 262: addr-=memsetstart;
! 263: }
! 264:
! 265: /* The data segment consists of actual data, but a part of it is
! 266: * data initialized to 0, the .bss section. This section is not
! 267: * actually put in the file to save space, but the ELF loader
! 268: * (that's us) is expected to allocate that data at program
! 269: * start. */
! 270: memsetend=p[i].p_memsz-p[i].p_filesz;
! 271: if (memsetend) {
! 272: /* We have a .bss. We need to handle two cases. First: if
! 273: * the number of bytes is small enough to fit on the last page
! 274: * we already mapped for the data, all we need to do is memset
! 275: * it. Otherwise we needto memset the rest of that page and
! 276: * map some additional pages after it. */
! 277: size_t bytes_on_last_page=(-len)&4095;
! 278: if (memsetend<bytes_on_last_page)
! 279: len+=memsetend;
! 280: else {
! 281: len+=bytes_on_last_page;
! 282: additional=memsetend-bytes_on_last_page;
! 283: memsetend=bytes_on_last_page;
! 284: }
! 285: }
! 286:
! 287: c=mmap((char*)addr,len,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_FIXED,fd,ofs);
! 288: if (c==MAP_FAILED) {
! 289: __write2("mmap failed!\n");
! 290: return 1;
! 291: }
! 292:
! 293: if (memsetstart) _memset(c,0,memsetstart);
! 294: if (memsetend) _memset(c+len-memsetend,0,memsetend);
! 295: if (additional) {
! 296: char* tmp=mmap(c+len,additional,PROT_READ|PROT_WRITE,MAP_PRIVATE|MAP_ANONYMOUS,-1,0);
! 297: if (tmp==MAP_FAILED) {
! 298: __write2("mmap failed!\n");
! 299: return 1;
! 300: }
! 301: }
! 302: D->data=c+memsetstart; D->datalen=len-memsetstart;
! 303: D->codeplus=codeplus;
! 304: }
! 305: }
! 306: }
! 307: #if 0
! 308: /* map the section table separately */
! 309: {
! 310: size_t delta=e->e_shoff&4095;
! 311: s=mmap(0,delta+e->e_shnum*e->e_shentsize,PROT_READ,MAP_SHARED,fd,e->e_shoff-delta);
! 312: if (s==MAP_FAILED) {
! 313: __write2("mmap failed!\n");
! 314: return 1;
! 315: }
! 316: D->s=(shdr*)((char*)s + delta);
! 317: }
! 318: #endif
! 319: return 0;
! 320: }
! 321:
! 322:
! 323: static int __loadlibrary(const char* fn) {
! 324: struct dll* D;
! 325: int fd;
! 326: char buf[1000];
! 327: ehdr* e;
! 328: phdr* p;
! 329: shdr* s;
! 330: size_t i;
! 331: char* code=0,* data=0;
! 332: char* base=0;
! 333: size_t codelen,datalen;
! 334: #if 0
! 335: __write1("trying ");
! 336: __write1(fn);
! 337: __write1("\n");
! 338: #endif
! 339: fd=open(fn,O_RDONLY);
! 340: if (fd==-1) return -1;
! 341: if (read(fd,buf,1000)<1000) {
! 342: kaputt:
! 343: close(fd);
! 344: return -1;
! 345: }
! 346: if (_memcmp(buf,"\177ELF",4)) goto kaputt;
! 347: e=(ehdr*)buf;
! 348:
! 349: if (e->e_ident[4] != (sizeof(size_t)/4) || // wrong word size
! 350: e->e_type != ET_DYN || // not shared object
! 351: e->e_machine != // for different architecture
! 352: #if defined(__x86_64__)
! 353: EM_X86_64
! 354: #elif defined(__i386__)
! 355: EM_386
! 356: #else
! 357: #error architecture not recognized, please add
! 358: #endif
! 359: ||
! 360: e->e_phentsize != sizeof(phdr) || // wrong program header entry size
! 361: e->e_phnum > 20 || // too many program header entries
! 362: e->e_shentsize !=sizeof(shdr) || // wrong section header entry size
! 363: e->e_shnum > 100) // too many sections
! 364: goto kaputt;
! 365:
! 366:
! 367: if (e->e_phoff>=1000 || e->e_phentsize*e->e_phnum>1000-e->e_phoff) {
! 368: size_t wanted=e->e_phentsize*e->e_phnum;
! 369: p=alloca(wanted);
! 370: if (pread64(fd,p,wanted,e->e_phoff)!=wanted)
! 371: goto kaputt;
! 372: } else
! 373: p=(phdr*)(buf+e->e_phoff);
! 374:
! 375: struct dll dll;
! 376: if (map_sections(fd,e,p,&dll)) {
! 377: __write2("map_sections failed\n");
! 378: goto kaputt;
! 379: }
! 380:
! 381: close(fd);
! 382:
! 383: {
! 384: const char* tmp;
! 385: for (i=0; fn[i]; ++i)
! 386: if (fn[i]=='/') tmp=fn+i;
! 387: ++tmp;
! 388: D=_malloc(sizeof(struct dll)+_strlen(tmp));
! 389: _stpcpy(D->name,tmp);
! 390: }
! 391: D->next=0;
! 392: D->code=dll.code; D->codelen=dll.codelen;
! 393: D->data=dll.data; D->datalen=dll.datalen;
! 394: D->s=dll.s;
! 395: D->e=dll.e;
! 396: D->codeplus=dll.codeplus;
! 397: {
! 398: struct dll** x;
! 399: for (x=&dlls; *x; x=&(*x)->next) ;
! 400: *x=D;
! 401: }
! 402: return 0;
! 403: }
! 404:
! 405: static int loadlibrary(const char* fn) {
! 406: char lp[200];
! 407: int r;
! 408: char* c;
! 409: const char* shortname=fn;
! 410: struct dll* d;
! 411:
! 412: {
! 413: size_t i;
! 414: for (i=0; fn[i]; ++i)
! 415: if (fn[i]=='/') shortname=fn+i+1;
! 416: }
! 417:
! 418: if (_strlen(fn)>50) return -1;
! 419: for (d=dlls; d; d=d->next)
! 420: if (!_strcmp(d->name,shortname))
! 421: return 0;
! 422:
! 423: __write1("loadlibrary(\"");
! 424: __write1(fn);
! 425: __write1("\")\n");
! 426: if (fn[0]=='/') {
! 427: return __loadlibrary(fn);
! 428: }
! 429:
! 430: c=_stpcpy(lp,path);
! 431: *c++='/';
! 432: _stpcpy(c,fn);
! 433: r=__loadlibrary(lp);
! 434: if (r==0) return r;
! 435: if (ldlp) {
! 436: size_t i;
! 437: char* d;
! 438: c=ldlp;
! 439: for (i=0; ; ++i) {
! 440: again:
! 441: if (c[i]==':' || c[i]==0) {
! 442: if (i<100) {
! 443: lp[i]='/';
! 444: _stpcpy(lp+i+1,fn);
! 445: r=__loadlibrary(lp);
! 446: if (r==0) return;
! 447: }
! 448: if (c[i]==0) break;
! 449: c+=i+1; i=0; goto again;
! 450: } else
! 451: if (i<100) lp[i]=c[i];
! 452: }
! 453: }
! 454: return r;
! 455: }
! 456:
! 457: static int loadlibs(ehdr* e,char* codemap,char* datamap,shdr* s) {
! 458: size_t i;
! 459: phdr* p=(phdr*)((char*)e+e->e_phoff);
! 460: phdr* code,* data;
! 461: dyn* d;
! 462: size_t dnum,dynstrlen;
! 463: char* dynstr;
! 464:
! 465: /* we know we have exactly one code and exactly one data segment,
! 466: * otherwise we wouldn't have gotten this far */
! 467: for (i=0; i<e->e_phnum; ++i) {
! 468: if (p[i].p_type==PT_LOAD)
! 469: if (p[i].p_flags&PF_X)
! 470: code=p+i;
! 471: else
! 472: data=p+i;
! 473: }
! 474:
! 475: d=0; dnum=0; dynstr=0; dynstrlen=0;
! 476: for (i=0; i<e->e_shnum; ++i) {
! 477: if (s[i].sh_type==SHT_DYNAMIC) {
! 478: /* dynamic section must be in data section */
! 479: if (s[i].sh_offset < data->p_offset || s[i].sh_offset+s[i].sh_size<s[i].sh_offset || s[i].sh_offset+s[i].sh_size > data->p_offset+data->p_memsz ||
! 480: s[i].sh_addr < data->p_vaddr || s[i].sh_addr+s[i].sh_size > data->p_vaddr+data->p_memsz || s[i].sh_entsize!=sizeof(dyn)) {
! 481: __write2("invalid dynamic section offset/size\n");
! 482: return 1;
! 483: }
! 484: d=(dyn*)(datamap+s[i].sh_addr-data->p_vaddr);
! 485: dnum=s[i].sh_size/s[i].sh_entsize;
! 486: } else if (s[i].sh_type==SHT_STRTAB) {
! 487: /* not sure how to keep the strtabs apart */
! 488: if (s[i].sh_offset < code->p_offset || s[i].sh_offset+s[i].sh_size<s[i].sh_offset || s[i].sh_offset+s[i].sh_size > code->p_offset+code->p_memsz ||
! 489: s[i].sh_addr < code->p_vaddr || s[i].sh_addr+s[i].sh_size > code->p_vaddr+code->p_memsz) continue;
! 490: dynstr=codemap+s[i].sh_addr-code->p_vaddr;
! 491: dynstrlen=s[i].sh_size;
! 492: if (!dynstrlen || dynstr[dynstrlen-1]) {
! 493: __write2("corrupt dynstr section\n");
! 494: return 1;
! 495: }
! 496: }
! 497: // printf("section %d type %d flags %x addr %p off %lx size %lx link %d info %d align %d entsize %d\n",
! 498: // s[i].sh_name,s[i].sh_type,s[i].sh_flags,s[i].sh_offset,s[i].sh_size,s[i].sh_link,s[i].sh_info,s[i].sh_addralign,s[i].sh_entsize);
! 499: }
! 500:
! 501: /* we now have a dynamic section we can traverse */
! 502: for (i=0; i<dnum; ++i) {
! 503: if (d[i].d_tag==DT_NEEDED) {
! 504: #if 0
! 505: __write1("needed library: ");
! 506: __write1(dynstr+d[i].d_un.d_val);
! 507: __write1("\n");
! 508: #endif
! 509: if (loadlibrary(dynstr+d[i].d_un.d_val)) {
! 510: __write2("library ");
! 511: __write2(dynstr+d[i].d_un.d_val);
! 512: __write2(" not found!\n");
! 513: exit(2);
! 514: }
! 515: }
! 516: }
! 517:
! 518: return 0;
! 519: }
! 520:
! 521: static unsigned int elf_hash(const unsigned char *name) {
! 522: unsigned int h=0, g;
! 523:
! 524: while (*name) {
! 525: h = (h<<4) + *(name++);
! 526: if ((g = h&0xf0000000)) h ^= g>>24;
! 527: h ^= g;
! 528: }
! 529: return h;
! 530: }
! 531:
! 532: static uint_fast32_t gnu_hash(const unsigned char *s) {
! 533: unsigned char c;
! 534: uint_fast32_t h=5381;
! 535: for(c=*s;(c!='\0');c=*++s) {
! 536: // h=h*33+c;
! 537: h=((h<<5)+h)+c;
! 538: }
! 539: return (h&0xffffffff);
! 540: }
! 541:
! 542: static char* dlsym(const char* symbol) {
! 543: struct dll* x;
! 544: for (x=&dllroot; x; x=x->next) {
! 545: size_t i;
! 546: shdr* s=(shdr*)((char*)x->e + x->e->e_shoff);
! 547: dyn* d;
! 548: sym* sy;
! 549: const char* strtab;
! 550: size_t dnum;
! 551: int* hash=0;
! 552: for (i=0; i<x->e->e_shnum; ++i)
! 553: if (s[i].sh_type==SHT_DYNAMIC) {
! 554: d=(dyn*)(x->codeplus + s[i].sh_addr);
! 555: dnum=s[i].sh_size/s[i].sh_entsize;
! 556: break;
! 557: }
! 558:
! 559: for (i=0; i<dnum; ++i) {
! 560: if (d[i].d_tag == DT_HASH)
! 561: hash=(int*)((char*)x->codeplus + d[i].d_un.d_ptr);
! 562: else if (d[i].d_tag == DT_SYMTAB)
! 563: sy=(sym*)((char*)(x->codeplus+d[i].d_un.d_ptr));
! 564: else if (d[i].d_tag == DT_STRTAB)
! 565: strtab=(char*)(x->codeplus+d[i].d_un.d_ptr);
! 566: }
! 567:
! 568: /* hash[0] is the number of buckets. */
! 569: /* hash[1] is the hash chain length, not used here */
! 570: size_t bhash=elf_hash(symbol)%hash[0];
! 571: unsigned int* chain=hash+2+hash[0];
! 572: unsigned int index;
! 573: for (index=(hash+2)[bhash]; index; index=chain[index]) {
! 574: #if 0
! 575: __write1(strtab+sy[index].st_name); __write1("\n");
! 576: #endif
! 577: if (sy[index].st_value && sy[index].st_shndx!=SHN_UNDEF && !_strcmp(strtab+sy[index].st_name,symbol)) {
! 578: return (char*)x->codeplus+sy[index].st_value;
! 579: }
! 580: }
! 581: #if 0
! 582: if (x->next) {
! 583: __write1(" ... next: ");
! 584: __write1(x->next->name);
! 585: __write1("\n");
! 586: }
! 587: #endif
! 588: }
! 589: return 0;
! 590: }
! 591:
! 592: int main(int argc,char* argv[],char* envp[]) {
! 593: int fd;
! 594: size_t l;
! 595: char* m;
! 596: char buf[1000];
! 597: ehdr* e;
! 598: phdr* p;
! 599: phdr* code=0,* data=0;
! 600: shdr* s;
! 601: dyn* d;
! 602: size_t dnum;
! 603: char* dynstr;
! 604: size_t dynstrlen;
! 605: size_t i;
! 606:
! 607: #if 0
! 608: {
! 609: fd=open("/proc/self/maps",O_RDONLY);
! 610: if (fd!=-1) {
! 611: size_t l;
! 612: do {
! 613: l=read(fd,buf,sizeof(buf));
! 614: write(1,buf,l);
! 615: } while (l==sizeof(buf));
! 616: close(fd);
! 617: }
! 618: }
! 619: #endif
! 620: if (argc<2) {
! 621: __write2("usage: ld.so /path/to/binary\n");
! 622: return 0;
! 623: }
! 624: fd=open("/etc/diet.ld.conf",O_RDONLY);
! 625: if (fd!=-1) {
! 626: int r=read(fd,path,99);
! 627: if (r>0) path[r]=0;
! 628: while (r>0 && path[r-1]=='\n') path[--r]=0;
! 629: close(fd);
! 630: }
! 631: for (i=0; envp[i]; ++i) {
! 632: if (_memcmp(envp[i],"LD_LIBRARY_PATH=",16)==0)
! 633: ldlp=envp[i]+16;
! 634: }
! 635: fd=open(argv[1],O_RDONLY);
! 636: if (fd==-1) {
! 637: __write2("could not open \"");
! 638: __write2(argv[1]);
! 639: __write2("\".\n");
! 640: return 1;
! 641: }
! 642: l=read(fd,buf,1000);
! 643: if (l<sizeof(ehdr) || _memcmp(buf,"\177ELF",4)) {
! 644: kaputt:
! 645: __write2("invalid ELF file \"");
! 646: close(fd);
! 647: return 1;
! 648: }
! 649: e=(ehdr*)buf;
! 650:
! 651: if (e->e_ident[4] != (sizeof(size_t)/4)) {
! 652: __write2("wrong word size!\n");
! 653: return 1;
! 654: }
! 655: #if 0
! 656: if (e->e_ident[7] != ELFOSABI_LINUX) {
! 657: __write2("ABI not Linux!\n");
! 658: return 1;
! 659: }
! 660: #endif
! 661: if (e->e_type != ET_EXEC) {
! 662: __write2("not an executable!\n");
! 663: return 1;
! 664: }
! 665: if (e->e_machine !=
! 666: #if defined(__x86_64__)
! 667: EM_X86_64
! 668: #elif defined(__i386__)
! 669: EM_386
! 670: #else
! 671: #error architecture not recognized, please add
! 672: #endif
! 673: ) {
! 674: __write2("invalid architecture!\n");
! 675: return 1;
! 676: }
! 677:
! 678: if (e->e_phentsize != sizeof(phdr)) {
! 679: __write2("invalid phentsize!\n");
! 680: return 1;
! 681: }
! 682: if (e->e_phnum > 20) {
! 683: __write2("phnum too large!\n");
! 684: return 1;
! 685: }
! 686: if (e->e_shentsize != sizeof(shdr)) {
! 687: __write2("invalid shentsize!\n");
! 688: return 1;
! 689: }
! 690: if (e->e_shnum > 100) {
! 691: __write2("shnum too large!\n");
! 692: return 1;
! 693: }
! 694:
! 695: if (e->e_phoff>=l || e->e_phentsize*e->e_phnum>l-e->e_phoff) {
! 696: size_t wanted=e->e_phentsize*e->e_phnum;
! 697: p=alloca(wanted);
! 698: if (pread64(fd,p,wanted,e->e_phoff)!=wanted)
! 699: goto kaputt;
! 700: } else
! 701: p=(phdr*)(buf+e->e_phoff);
! 702:
! 703: dlls=&dllroot;
! 704: if (map_sections(fd,e,p,&dllroot)) {
! 705: __write2("map_sections failed!\n");
! 706: return 1;
! 707: }
! 708: close(fd);
! 709:
! 710: loadlibs(dllroot.e,dllroot.code,dllroot.data,dllroot.s);
! 711:
! 712: /* now load the prerequisites of the libraries we loaded */
! 713: {
! 714: struct dll* x;
! 715: for (x=dlls; x; x=x->next) {
! 716: loadlibs(x->e,x->code,x->data,x->s);
! 717: }
! 718: }
! 719:
! 720: {
! 721: char* x=dlsym("theint");
! 722: __write1("done");
! 723: }
! 724:
! 725: #if 0
! 726: printf("jump to %p\n",e->e_entry);
! 727: for (i=0; i<16; ++i) {
! 728: printf("%02x ",((unsigned char*)e->e_entry)[i]);
! 729: }
! 730: #endif
! 731:
! 732: return 0;
! 733: }
LinuxTV legacy CVS <linuxtv.org/cvs>