$ diff linker.c linker_original.c 30c30,31 < #include --- > #include > #include "/home/neon/git/CCR/Scripts/Shell/builtins/printfmacro.h" 32c33,35 < #include --- > > #include > #define Elf32_Header Elf32_Ehdr 57c60 < #define TRACE_APP_NAME "ld.so" --- > #define TRACE_APP_NAME "Dynamic Linker" 62c65 < #include --- > #include "./trace.h" 69,70c72,73 < #include "../lib/list.c" < #include "../lib/hashmap.c" --- > #include "./list.c" > #include "./hashmap.c" 271a275,801 > int prot_from_phdr(const int p_flags) > { > int prot = 0; > if (p_flags & PF_R) > { > fprintf(stderr, "PROT_READ|"); > prot |= PROT_READ; > } > if (p_flags & PF_W) > { > fprintf(stderr, "PROT_WRITE|"); > prot |= PROT_WRITE; > } > if (p_flags & PF_X) > { > fprintf(stderr, "PROT_EXEC|"); > prot |= PROT_EXEC; > } > return prot; > } > > uintptr_t round_down(uintptr_t value, uintptr_t size) > { > TRACE_LD("calling %s", __func__); > uintptr_t result = 0; > result = (value/size)*size; > TRACE_LD("returning %014p", result); > return result; > } > > Elf32_Dyn DYN_EMPTY = {0}; > > Elf32_Dyn * > get_dynamic_entry(Elf32_Dyn *dynamic, int field) > { > TRACE_LD("called get_dynamic_entry"); > > // Name Value d_un Executable Shared Object > // DT_NULL 0 ignored mandatory mandatory > // DT_NEEDED 1 d_val optional optional > // DT_PLTRELSZ 2 d_val optional optional > // DT_PLTGOT 3 d_ptr optional optional > // DT_HASH 4 d_ptr mandatory mandatory > // DT_STRTAB 5 d_ptr mandatory mandatory > // DT_SYMTAB 6 d_ptr mandatory mandatory > // DT_RELA 7 d_ptr mandatory optional > // DT_RELASZ 8 d_val mandatory optional > // DT_RELAENT 9 d_val mandatory optional > // DT_STRSZ 10 d_val mandatory mandatory > // DT_SYMENT 11 d_val mandatory mandatory > // DT_INIT 12 d_ptr optional optional > // DT_FINI 13 d_ptr optional optional > // DT_SONAME 14 d_val ignored optional > // DT_RPATH 15 d_val optional ignored > // DT_SYMBOLIC 16 ignored ignored optional > // DT_REL 17 d_ptr mandatory optional > // DT_RELSZ 18 d_val mandatory optional > // DT_RELENT 19 d_val mandatory optional > // DT_PLTREL 20 d_val optional optional > // DT_DEBUG 21 d_ptr optional ignored > // DT_TEXTREL 22 ignored optional optional > // DT_JMPREL 23 d_ptr optional optional > // DT_BIND_NOW 24 ignored optional optional > // DT_LOPROC 0x70000000 unspecified unspecified unspecified > // DT_HIPROC 0x7fffffff unspecified unspecified unspecified > // > // DT_NULL An entry with a DT_NULL tag marks the end of the _DYNAMIC array. > // DT_NEEDED This element holds the string table offset of a null-terminated string, giving > // the name of a needed library. The offset is an index into the table recorded > // in the DT_STRTAB entry. See "Shared Object Dependencies'' for more > // information about these names. The dynamic array may contain multiple > // entries with this type. These entries' relative order is significant, though > // their relation to entries of other types is not. > // > // DT_PLTRELSZ This element holds the total size, in bytes, of the relocation entries > // associated with the procedure linkage table. If an entry of type DT_JMPREL > // is present, a DT_PLTRELSZ must accompany it. > // > // DT_PLTGOT This element holds an address associated with the procedure linkage table > // and/or the global offset table. > // > // DT_HASH This element holds the address of the symbol hash table, described in "Hash > // Table". This hash table refers to the symbol table referenced by the > // DT_SYMTAB element. > // > // DT_STRTAB This element holds the address of the string table, described in Chapter 1. > // Symbol names, library names, and other strings reside in this table. > // > // DT_SYMTAB This element holds the address of the symbol table, described in > // Chapter 1, with Elf32_Sym entries for the 32-bit class of files. > // > // DT_RELA This element holds the address of a relocation table, described in > // Chapter 1. Entries in the table have explicit addends, such as Elf32_Rela > // for the 32-bit file class. An object file may have multiple relocation > // sections. When building the relocation table for an executable or shared > // object file, the link editor catenates those sections to form a single table. > // Although the sections remain independent in the object file, the dynamic > // linker sees a single table. When the dynamic linker creates the process > // image for an executable file or adds a shared object to the process image, > // it reads the relocation table and performs the associated actions. If this > // element is present, the dynamic structure must also have DT_RELASZ and > // DT_RELAENT elements. When relocation is "mandatory" for a file, either > // DT_RELA or DT_REL may occur (both are permitted but not required). > // > // DT_RELASZ This element holds the total size, in bytes, of the DT_RELA relocation table. > // > // DT_RELAENT This element holds the size, in bytes, of the DT_RELA relocation entry. > // > // DT_STRSZ This element holds the size, in bytes, of the string table. > // > // DT_SYMENT This element holds the size, in bytes, of a symbol table entry. > // > // DT_INIT This element holds the address of the initialization function, discussed in > // "Initialization and Termination Functions" below. > // > // DT_FINI This element holds the address of the termination function, discussed in > // "Initialization and Termination Functions" below. > // > // DT_SONAME This element holds the string table offset of a null-terminated string, giving > // the name of the shared object. The offset is an index into the table recorded > // in the DT_STRTAB entry. See "Shared Object Dependencies" below for > // more information about these names. > // > // DT_RPATH This element holds the string table offset of a null-terminated search library > // search path string, discussed in "Shared Object Dependencies". The offset > // is an index into the table recorded in the DT_STRTAB entry. > // > // DT_SYMBOLIC This element's presence in a shared object library alters the dynamic linker's > // symbol resolution algorithm for references within the library. Instead of > // starting a symbol search with the executable file, the dynamic linker starts > // from the shared object itself. If the shared object fails to supply the > // referenced symbol, the dynamic linker then searches the executable file and > // other shared objects as usual. > // > // DT_REL This element is similar to DT_RELA, except its table has implicit addends, > // such as Elf32_Rel for the 32-bit file class. If this element is present, the > // dynamic structure must also have DT_RELSZ and DT_RELENT elements. > // > // DT_RELSZ This element holds the total size, in bytes, of the DT_REL relocation table. > // > // DT_RELENT This element holds the size, in bytes, of the DT_REL relocation entry. > // > // DT_PLTREL This member specifies the type of relocation entry to which the procedure > // linkage table refers. The d_val member holds DT_REL or DT_RELA , as > // appropriate. All relocations in a procedure linkage table must use the same > // relocation. > // > // DT_DEBUG This member is used for debugging. Its contents are not specified in this > // document. > // > // DT_TEXTREL This member's absence signifies that no relocation entry should cause a > // modification to a non-writable segment, as specified by the segment > // permissions in the program header table. If this member is present, one or > // more relocation entries might request modifications to a non-writable > // segment, and the dynamic linker can prepare accordingly. > // > // DT_JMPREL If present, this entries d_ptr member holds the address of relocation > // entries associated solely with the procedure linkage table. Separating these > // relocation entries lets the dynamic linker ignore them during process > // initialization, if lazy binding is enabled. If this entry is present, the related > // entries of types DT_PLTRELSZ and DT_PLTREL must also be present. > // > // DT_BIND_NOW If present in a shared object or executable, this entry instructs the dynamic > // linker to process all relocations for the object containing this entry before > // transferring control to the program. The presence of this entry takes > // precedence over a directive to use lazy binding for this object when > // specified through the environment or via dlopen( BA_LIB). > // > // DT_LOPROC through DT_HIPROC > // Values in this inclusive range are reserved for processor-specific semantics. > // If meanings are specified, the processor supplement explains them. > // > // Except for the DT_NULL element at the end of the library[library_index].array, and the relative order of DT_NEEDED > // elements, entries may appear in any order. Tag values not appearing in the table are reserved. > > > for (; dynamic->d_tag != DT_NULL; dynamic++) { > fprintf(stderr, "testing if "); > /* Legal values for d_tag (dynamic entry type). */ > > // #define DT_NULL 0 /* Marks end of dynamic section */ > // #define DT_NEEDED 1 /* Name of needed library */ > // #define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ > // #define DT_PLTGOT 3 /* Processor defined value */ > // #define DT_HASH 4 /* Address of symbol hash table */ > // #define DT_STRTAB 5 /* Address of string table */ > // #define DT_SYMTAB 6 /* Address of symbol table */ > // #define DT_RELA 7 /* Address of Rela relocs */ > // #define DT_RELASZ 8 /* Total size of Rela relocs */ > // #define DT_RELAENT 9 /* Size of one Rela reloc */ > // #define DT_STRSZ 10 /* Size of string table */ > // #define DT_SYMENT 11 /* Size of one symbol table entry */ > // #define DT_INIT 12 /* Address of init function */ > // #define DT_FINI 13 /* Address of termination function */ > // #define DT_SONAME 14 /* Name of shared object */ > // #define DT_RPATH 15 /* Library search path (deprecated) */ > // #define DT_SYMBOLIC 16 /* Start symbol search here */ > // #define DT_REL 17 /* Address of Rel relocs */ > // #define DT_RELSZ 18 /* Total size of Rel relocs */ > // #define DT_RELENT 19 /* Size of one Rel reloc */ > // #define DT_PLTREL 20 /* Type of reloc in PLT */ > // #define DT_DEBUG 21 /* For debugging; unspecified */ > // #define DT_TEXTREL 22 /* Reloc might modify .text */ > // #define DT_JMPREL 23 /* Address of PLT relocs */ > // #define DT_BIND_NOW 24 /* Process relocations of object */ > // #define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ > // #define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ > // #define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ > // #define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ > // #define DT_RUNPATH 29 /* Library search path */ > // #define DT_FLAGS 30 /* Flags for the object being loaded */ > // #define DT_ENCODING 32 /* Start of encoded range */ > // #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ > // #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ > // #define DT_NUM 34 /* Number used */ > // #define DT_LOOS 0x6000000d /* Start of OS-specific */ > // #define DT_HIOS 0x6ffff000 /* End of OS-specific */ > // #define DT_LOPROC 0x70000000 /* Start of processor-specific */ > // #define DT_HIPROC 0x7fffffff /* End of processor-specific */ > // #define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ > switch (dynamic->d_tag) { > case DT_NULL: > fprintf(stderr, "DT_NULL"); > break; > case DT_NEEDED: > fprintf(stderr, "DT_NEEDED"); > break; > case DT_PLTRELSZ: > fprintf(stderr, "DT_PLTRELSZ"); > break; > case DT_PLTGOT: > fprintf(stderr, "DT_PLTGOT"); > break; > case DT_HASH: > fprintf(stderr, "DT_HASH"); > break; > case DT_STRTAB: > fprintf(stderr, "DT_STRTAB"); > break; > case DT_SYMTAB: > fprintf(stderr, "DT_SYMTAB"); > break; > case DT_RELA: > fprintf(stderr, "DT_RELA"); > break; > case DT_RELASZ: > fprintf(stderr, "DT_RELASZ"); > break; > case DT_RELAENT: > fprintf(stderr, "DT_RELAENT"); > break; > case DT_STRSZ: > fprintf(stderr, "DT_STRSZ"); > break; > case DT_SYMENT: > fprintf(stderr, "DT_SYMENT"); > break; > case DT_INIT: > fprintf(stderr, "DT_INIT"); > break; > case DT_FINI: > fprintf(stderr, "DT_FINI"); > break; > case DT_SONAME: > fprintf(stderr, "DT_SONAME"); > break; > case DT_RPATH: > fprintf(stderr, "DT_RPATH"); > break; > case DT_SYMBOLIC: > fprintf(stderr, "DT_SYMBOLIC"); > break; > case DT_REL: > fprintf(stderr, "DT_REL"); > break; > case DT_RELSZ: > fprintf(stderr, "DT_RELSZ"); > break; > case DT_RELENT: > fprintf(stderr, "DT_RELENT"); > break; > case DT_PLTREL: > fprintf(stderr, "DT_PLTREL"); > break; > case DT_DEBUG: > fprintf(stderr, "DT_DEBUG"); > break; > case DT_TEXTREL: > fprintf(stderr, "DT_TEXTREL"); > break; > case DT_JMPREL: > fprintf(stderr, "DT_JMPREL"); > break; > case DT_BIND_NOW: > fprintf(stderr, "DT_BIND_NOW"); > break; > case DT_INIT_ARRAY: > fprintf(stderr, "DT_INIT_ARRAY"); > break; > case DT_FINI_ARRAY: > fprintf(stderr, "DT_FINI_ARRAY"); > break; > case DT_INIT_ARRAYSZ: > fprintf(stderr, "DT_INIT_ARRAYSZ"); > break; > case DT_FINI_ARRAYSZ: > fprintf(stderr, "DT_FINI_ARRAYSZ"); > break; > case DT_RUNPATH: > fprintf(stderr, "DT_RUNPATH"); > break; > case DT_FLAGS: > fprintf(stderr, "DT_FLAGS"); > break; > case DT_ENCODING: > fprintf(stderr, "DT_ENCODING (or DT_PREINIT_ARRAY)"); > break; > case DT_PREINIT_ARRAYSZ: > fprintf(stderr, "DT_PREINIT_ARRAYSZ"); > break; > case DT_NUM: > fprintf(stderr, "DT_NUM"); > break; > case DT_LOOS: > fprintf(stderr, "DT_LOOS"); > break; > case DT_HIOS: > fprintf(stderr, "DT_HIOS"); > break; > case DT_LOPROC: > fprintf(stderr, "DT_LOPROC"); > break; > case DT_HIPROC: > fprintf(stderr, "DT_HIPROC (or DT_FILTER)"); > break; > case DT_PROCNUM: > fprintf(stderr, "DT_PROCNUM"); > break; > case DT_VERSYM: > fprintf(stderr, "DT_VERSYM"); > break; > case DT_RELACOUNT: > fprintf(stderr, "DT_RELACOUNT"); > break; > case DT_RELCOUNT: > fprintf(stderr, "DT_RELCOUNT"); > break; > case DT_FLAGS_1: > fprintf(stderr, "DT_FLAGS_1"); > break; > case DT_VERDEF: > fprintf(stderr, "DT_VERDEF"); > break; > case DT_VERDEFNUM: > fprintf(stderr, "DT_VERDEFNUM"); > break; > case DT_VERNEED: > fprintf(stderr, "DT_VERNEED"); > break; > case DT_VERNEEDNUM: > fprintf(stderr, "DT_VERNEEDNUM"); > break; > case DT_AUXILIARY: > fprintf(stderr, "DT_AUXILIARY"); > break; > default: > fprintf(stderr, "%d", dynamic->d_tag); > break; > } > fprintf(stderr, " == "); > switch (field) { > case DT_NULL: > fprintf(stderr, "DT_NULL"); > break; > case DT_NEEDED: > fprintf(stderr, "DT_NEEDED"); > break; > case DT_PLTRELSZ: > fprintf(stderr, "DT_PLTRELSZ"); > break; > case DT_PLTGOT: > fprintf(stderr, "DT_PLTGOT"); > break; > case DT_HASH: > fprintf(stderr, "DT_HASH"); > break; > case DT_STRTAB: > fprintf(stderr, "DT_STRTAB"); > break; > case DT_SYMTAB: > fprintf(stderr, "DT_SYMTAB"); > break; > case DT_RELA: > fprintf(stderr, "DT_RELA"); > break; > case DT_RELASZ: > fprintf(stderr, "DT_RELASZ"); > break; > case DT_RELAENT: > fprintf(stderr, "DT_RELAENT"); > break; > case DT_STRSZ: > fprintf(stderr, "DT_STRSZ"); > break; > case DT_SYMENT: > fprintf(stderr, "DT_SYMENT"); > break; > case DT_INIT: > fprintf(stderr, "DT_INIT"); > break; > case DT_FINI: > fprintf(stderr, "DT_FINI"); > break; > case DT_SONAME: > fprintf(stderr, "DT_SONAME"); > break; > case DT_RPATH: > fprintf(stderr, "DT_RPATH"); > break; > case DT_SYMBOLIC: > fprintf(stderr, "DT_SYMBOLIC"); > break; > case DT_REL: > fprintf(stderr, "DT_REL"); > break; > case DT_RELSZ: > fprintf(stderr, "DT_RELSZ"); > break; > case DT_RELENT: > fprintf(stderr, "DT_RELENT"); > break; > case DT_PLTREL: > fprintf(stderr, "DT_PLTREL"); > break; > case DT_DEBUG: > fprintf(stderr, "DT_DEBUG"); > break; > case DT_TEXTREL: > fprintf(stderr, "DT_TEXTREL"); > break; > case DT_JMPREL: > fprintf(stderr, "DT_JMPREL"); > break; > case DT_BIND_NOW: > fprintf(stderr, "DT_BIND_NOW"); > break; > case DT_INIT_ARRAY: > fprintf(stderr, "DT_INIT_ARRAY"); > break; > case DT_FINI_ARRAY: > fprintf(stderr, "DT_FINI_ARRAY"); > break; > case DT_INIT_ARRAYSZ: > fprintf(stderr, "DT_INIT_ARRAYSZ"); > break; > case DT_FINI_ARRAYSZ: > fprintf(stderr, "DT_FINI_ARRAYSZ"); > break; > case DT_RUNPATH: > fprintf(stderr, "DT_RUNPATH"); > break; > case DT_FLAGS: > fprintf(stderr, "DT_FLAGS"); > break; > case DT_ENCODING: > fprintf(stderr, "DT_ENCODING (or DT_PREINIT_ARRAY)"); > break; > case DT_PREINIT_ARRAYSZ: > fprintf(stderr, "DT_PREINIT_ARRAYSZ"); > break; > case DT_NUM: > fprintf(stderr, "DT_NUM"); > break; > case DT_LOOS: > fprintf(stderr, "DT_LOOS"); > break; > case DT_HIOS: > fprintf(stderr, "DT_HIOS"); > break; > case DT_LOPROC: > fprintf(stderr, "DT_LOPROC"); > break; > case DT_HIPROC: > fprintf(stderr, "DT_HIPROC (or DT_FILTER)"); > break; > case DT_PROCNUM: > fprintf(stderr, "DT_PROCNUM"); > break; > case DT_VERSYM: > fprintf(stderr, "DT_VERSYM"); > break; > case DT_RELACOUNT: > fprintf(stderr, "DT_RELACOUNT"); > break; > case DT_RELCOUNT: > fprintf(stderr, "DT_RELCOUNT"); > break; > case DT_FLAGS_1: > fprintf(stderr, "DT_FLAGS_1"); > break; > case DT_VERDEF: > fprintf(stderr, "DT_VERDEF"); > break; > case DT_VERDEFNUM: > fprintf(stderr, "DT_VERDEFNUM"); > break; > case DT_VERNEED: > fprintf(stderr, "DT_VERNEED"); > break; > case DT_VERNEEDNUM: > fprintf(stderr, "DT_VERNEEDNUM"); > break; > case DT_AUXILIARY: > fprintf(stderr, "DT_AUXILIARY"); > break; > default: > fprintf(stderr, "%d (unknown)", field); > break; > } > fprintf(stderr, "\n"); > if (dynamic->d_tag == field) return dynamic; > } > TRACE_LD("returning 0"); > return &DYN_EMPTY; > } > > 279a810 > int PT_LOADS_CURRENT = 0; 289a821,829 > PT_LOADS_CURRENT = PT_LOADS_CURRENT + 1; > TRACE_LD("mapping PT_LOAD number %d", PT_LOADS_CURRENT); > TRACE_LD("\t\tp_flags: %014p", phdr.p_flags); > TRACE_LD("\t\tp_offset: %014p", phdr.p_offset); > TRACE_LD("\t\tp_vaddr: %014p", phdr.p_vaddr); > TRACE_LD("\t\tp_paddr: %014p", phdr.p_paddr); > TRACE_LD("\t\tp_filesz: %014p", phdr.p_filesz); > TRACE_LD("\t\tp_memsz: %014p", phdr.p_memsz); > TRACE_LD("\t\tp_align: %014p", phdr.p_align); 292,293c832,846 < sysfunc(TOARU_SYS_FUNC_MMAP, args); < --- > // sysfunc(TOARU_SYS_FUNC_MMAP, args); > > // [22:33] for args={addr,size}, that requests memory be allocated at virtual address `addr` for `size` bytes > #include > Elf32_Addr vaddr = round_down(phdr.p_vaddr, getpagesize()); > char * mem = (char*)(base + vaddr); > void * m = mmap(mem, phdr.p_memsz, PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); > if (m == MAP_FAILED) { > int err = errno; > TRACE_LD("map failed with %d and errno %d: %s", m, err, strerror(err)); > TRACE_LD("aborting"); > abort(); > } else { > TRACE_LD("map succeded with address: 0x%014x", m); > } 294a848 > TRACE_LD("seeking"); 296c850,852 < fread((void *)(base + phdr.p_vaddr), phdr.p_filesz, 1, object->file); --- > TRACE_LD("reading"); > fread(mem, 305, 1, object->file); > TRACE_LD("zeroing"); 301c857 < *(char *)(phdr.p_vaddr + base + r) = 0; --- > *(char *)(vaddr + base + r) = 0; 306,307c862,863 < if (end_addr < phdr.p_vaddr + base + phdr.p_memsz) { < end_addr = phdr.p_vaddr + base + phdr.p_memsz; --- > if (end_addr < vaddr + base + phdr.p_memsz) { > end_addr = vaddr + base + phdr.p_memsz; 314c870,872 < object->dynamic = (Elf32_Dyn *)(base + phdr.p_vaddr); --- > object->dynamic = (Elf32_Dyn *)(base + round_down(phdr.p_vaddr, getpagesize())); > TRACE_LD("obtaining list of dynamic entries"); > get_dynamic_entry(object->dynamic, -1); 323c881 < --- > fpp(TRACE_LD, object->base, PRINTF_END_WITHOUT_NEW_LINE) 339d896 < 340a898 > fpp(TRACE_LD, object->dynamic, PRINTF_END_WITHOUT_NEW_LINE) 345a904 > fpi(TRACE_LD, table->d_tag, PRINTF_END_WITHOUT_NEW_LINE) 346a906 > fpi(TRACE_LD, table->d_tag, PRINTF_END_WITHOUT_NEW_LINE) 380a941,943 > fpi(TRACE_LD, table->d_tag, PRINTF_END_WITHOUT_NEW_LINE) > TRACE_LD("obtaining list of dynamic entries"); > get_dynamic_entry(object->dynamic, -1); 383a947 > TRACE_LD("adding dependancy %s", object->dyn_string_table + table->d_un.d_val); 384a949 > abort(); 507a1073 > fpp(TRACE_LD, object->base, PRINTF_END_WITHOUT_NEW_LINE) 508a1075 > fpp(TRACE_LD, table, PRINTF_END_WITHOUT_NEW_LINE) 720c1287 < uintptr_t end_addr = object_load(main_obj, 0x0); --- > uintptr_t end_addr = object_load(main_obj, 0x40000000); 735a1303 > fpp(TRACE_LD, main_obj->dependencies, PRINTF_END_WITHOUT_NEW_LINE) 736a1305 > fpp(TRACE_LD, item, PRINTF_END_WITHOUT_NEW_LINE) 741a1311 > TRACE_LD("Loading dependency %s", lib_name); 821c1391,1392 < sysfunc(TOARU_SYS_FUNC_SETHEAP, args); --- > // sysfunc(TOARU_SYS_FUNC_SETHEAP, args); > sbrk(end_addr); 832c1403 < entry(argc-arg_offset,argv+arg_offset,environ); --- > entry(argc-arg_offset,argv+arg_offset,__environ);