| Upstream-Status: Inappropriate [embedded specific] |
| |
| Do data input/output handling according to endien-ness of the library file. That |
| enables use of ldconfig in the cross fashion for any architecture. |
| |
| 2011/04/04 |
| Richard Purdie <richard.purdie@linuxfoundation.org> |
| Nitin Kamble <nitin.a.kamble@intel.com> |
| |
| Index: ldconfig-native-2.12.1/readelflib.c |
| =================================================================== |
| --- ldconfig-native-2.12.1.orig/readelflib.c |
| +++ ldconfig-native-2.12.1/readelflib.c |
| @@ -38,6 +38,28 @@ do \ |
| } \ |
| while (0); |
| |
| +int be; |
| +static uint16_t read16(uint16_t x, int be) |
| +{ |
| + if (be) |
| + return be16toh(x); |
| + return le16toh(x); |
| +} |
| + |
| +static uint32_t read32(uint32_t x, int be) |
| +{ |
| + if (be) |
| + return be32toh(x); |
| + return le32toh(x); |
| +} |
| + |
| +static uint64_t read64(uint64_t x, int be) |
| +{ |
| + if (be) |
| + return be64toh(x); |
| + return le64toh(x); |
| +} |
| + |
| /* Returns 0 if everything is ok, != 0 in case of error. */ |
| int |
| process_elf_file32 (const char *file_name, const char *lib, int *flag, |
| @@ -59,15 +81,17 @@ process_elf_file32 (const char *file_nam |
| elf_header = (Elf32_Ehdr *) file_contents; |
| *osversion = 0; |
| |
| - if (elf_header->e_type != ET_DYN) |
| + be = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB); |
| + |
| + if (read16(elf_header->e_type, be) != ET_DYN) |
| { |
| error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name, |
| - elf_header->e_type); |
| + read16(elf_header->e_type, be)); |
| return 1; |
| } |
| |
| /* Get information from elf program header. */ |
| - elf_pheader = (Elf32_Phdr *) (elf_header->e_phoff + file_contents); |
| + elf_pheader = (Elf32_Phdr *) (read32(elf_header->e_phoff, be) + file_contents); |
| check_ptr (elf_pheader); |
| |
| /* The library is an elf library, now search for soname and |
| @@ -79,27 +103,27 @@ process_elf_file32 (const char *file_nam |
| dynamic_size = 0; |
| program_interpreter = NULL; |
| for (i = 0, segment = elf_pheader; |
| - i < elf_header->e_phnum; i++, segment++) |
| + i < read16(elf_header->e_phnum, be); i++, segment++) |
| { |
| check_ptr (segment); |
| |
| - switch (segment->p_type) |
| + switch (read32(segment->p_type, be)) |
| { |
| case PT_LOAD: |
| if (loadaddr == (Elf32_Addr) -1) |
| - loadaddr = segment->p_vaddr - segment->p_offset; |
| + loadaddr = read32(segment->p_vaddr, be) - read32(segment->p_offset, be); |
| break; |
| |
| case PT_DYNAMIC: |
| if (dynamic_addr) |
| error (0, 0, _("more than one dynamic segment\n")); |
| |
| - dynamic_addr = segment->p_offset; |
| - dynamic_size = segment->p_filesz; |
| + dynamic_addr = read32(segment->p_offset, be); |
| + dynamic_size = read32(segment->p_filesz, be); |
| break; |
| |
| case PT_INTERP: |
| - program_interpreter = (char *) (file_contents + segment->p_offset); |
| + program_interpreter = (char *) (file_contents + read32(segment->p_offset, be)); |
| check_ptr (program_interpreter); |
| |
| /* Check if this is enough to classify the binary. */ |
| @@ -113,20 +137,20 @@ process_elf_file32 (const char *file_nam |
| break; |
| |
| case PT_NOTE: |
| - if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4) |
| + if (!*osversion && read32(segment->p_filesz, be) >= 32 && segment->p_align >= 4) |
| { |
| Elf32_Word *abi_note = (Elf32_Word *) (file_contents |
| - + segment->p_offset); |
| - Elf32_Addr size = segment->p_filesz; |
| + + read32(segment->p_offset, be)); |
| + Elf32_Addr size = read32(segment->p_filesz, be); |
| |
| - while (abi_note [0] != 4 || abi_note [1] != 16 |
| - || abi_note [2] != 1 |
| + while (read32(abi_note [0], be) != 4 || read32(abi_note [1], be) != 16 |
| + || read32(abi_note [2], be) != 1 |
| || memcmp (abi_note + 3, "GNU", 4) != 0) |
| { |
| -#define ROUND(len) (((len) + sizeof (Elf32_Word)) - 1) & -sizeof (Elf32_Word))) |
| - Elf32_Addr) note_size = 3 * sizeof (Elf32_Word)) |
| - + ROUND (abi_note[0]) |
| - + ROUND (abi_note[1]); |
| +#define ROUND(len) (((len) + sizeof (Elf32_Word) - 1) & -sizeof (Elf32_Word)) |
| + Elf32_Addr note_size = 3 * sizeof (Elf32_Word) |
| + + ROUND (read32(abi_note[0], be)) |
| + + ROUND (read32(abi_note[1], be)); |
| |
| if (size - 32 < note_size || note_size == 0) |
| { |
| @@ -140,10 +164,10 @@ process_elf_file32 (const char *file_nam |
| if (size == 0) |
| break; |
| |
| - *osversion = (abi_note [4] << 24) | |
| - ((abi_note [5] & 0xff) << 16) | |
| - ((abi_note [6] & 0xff) << 8) | |
| - (abi_note [7] & 0xff); |
| + *osversion = (read32(abi_note [4], be) << 24) | |
| + ((read32(abi_note [5], be) & 0xff) << 16) | |
| + ((read32(abi_note [6], be) & 0xff) << 8) | |
| + (read32(abi_note [7], be) & 0xff); |
| } |
| break; |
| |
| @@ -167,13 +191,13 @@ process_elf_file32 (const char *file_nam |
| |
| /* Find the string table. */ |
| dynamic_strings = NULL; |
| - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; |
| + for (dyn_entry = dynamic_segment; read32(dyn_entry->d_tag, be) != DT_NULL; |
| ++dyn_entry) |
| { |
| check_ptr (dyn_entry); |
| - if (dyn_entry->d_tag == DT_STRTAB) |
| + if (read32(dyn_entry->d_tag, be) == DT_STRTAB) |
| { |
| - dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); |
| + dynamic_strings = (char *) (file_contents + read32(dyn_entry->d_un.d_val, be) - loadaddr); |
| check_ptr (dynamic_strings); |
| break; |
| } |
| @@ -183,15 +207,15 @@ process_elf_file32 (const char *file_nam |
| return 1; |
| |
| /* Now read the DT_NEEDED and DT_SONAME entries. */ |
| - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; |
| + for (dyn_entry = dynamic_segment; read32(dyn_entry->d_tag, be) != DT_NULL; |
| ++dyn_entry) |
| { |
| - if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME) |
| + if (read32(dyn_entry->d_tag, be) == DT_NEEDED || read32(dyn_entry->d_tag, be) == DT_SONAME) |
| { |
| - char *name = dynamic_strings + dyn_entry->d_un.d_val; |
| + char *name = dynamic_strings + read32(dyn_entry->d_un.d_val, be); |
| check_ptr (name); |
| |
| - if (dyn_entry->d_tag == DT_NEEDED) |
| + if (read32(dyn_entry->d_tag, be) == DT_NEEDED) |
| { |
| |
| if (*flag == FLAG_ELF) |
| @@ -208,7 +232,7 @@ process_elf_file32 (const char *file_nam |
| } |
| } |
| |
| - else if (dyn_entry->d_tag == DT_SONAME) |
| + else if (read32(dyn_entry->d_tag, be) == DT_SONAME) |
| *soname = xstrdup (name); |
| |
| /* Do we have everything we need? */ |
| @@ -246,15 +270,17 @@ process_elf_file64 (const char *file_nam |
| elf_header = (Elf64_Ehdr *) file_contents; |
| *osversion = 0; |
| |
| - if (elf_header->e_type != ET_DYN) |
| + be = (elf_header->e_ident[EI_DATA] == ELFDATA2MSB); |
| + |
| + if (read16(elf_header->e_type, be) != ET_DYN) |
| { |
| error (0, 0, _("%s is not a shared object file (Type: %d).\n"), file_name, |
| - elf_header->e_type); |
| + read16(elf_header->e_type, be)); |
| return 1; |
| } |
| |
| /* Get information from elf program header. */ |
| - elf_pheader = (Elf64_Phdr *) (elf_header->e_phoff + file_contents); |
| + elf_pheader = (Elf64_Phdr *) (read64(elf_header->e_phoff, be) + file_contents); |
| check_ptr (elf_pheader); |
| |
| /* The library is an elf library, now search for soname and |
| @@ -266,27 +292,27 @@ process_elf_file64 (const char *file_nam |
| dynamic_size = 0; |
| program_interpreter = NULL; |
| for (i = 0, segment = elf_pheader; |
| - i < elf_header->e_phnum; i++, segment++) |
| + i < read16(elf_header->e_phnum, be); i++, segment++) |
| { |
| check_ptr (segment); |
| |
| - switch (segment->p_type) |
| + switch (read32(segment->p_type, be)) |
| { |
| case PT_LOAD: |
| if (loadaddr == (Elf64_Addr) -1) |
| - loadaddr = segment->p_vaddr - segment->p_offset; |
| + loadaddr = read64(segment->p_vaddr, be) - read64(segment->p_offset, be); |
| break; |
| |
| case PT_DYNAMIC: |
| if (dynamic_addr) |
| error (0, 0, _("more than one dynamic segment\n")); |
| |
| - dynamic_addr = segment->p_offset; |
| - dynamic_size = segment->p_filesz; |
| + dynamic_addr = read64(segment->p_offset, be); |
| + dynamic_size = read32(segment->p_filesz, be); |
| break; |
| |
| case PT_INTERP: |
| - program_interpreter = (char *) (file_contents + segment->p_offset); |
| + program_interpreter = (char *) (file_contents + read64(segment->p_offset, be)); |
| check_ptr (program_interpreter); |
| |
| /* Check if this is enough to classify the binary. */ |
| @@ -300,20 +326,21 @@ process_elf_file64 (const char *file_nam |
| break; |
| |
| case PT_NOTE: |
| - if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4) |
| + if (!*osversion && read32(segment->p_filesz, be) >= 32 && read32(segment->p_align, be) >= 4) |
| { |
| Elf64_Word *abi_note = (Elf64_Word *) (file_contents |
| - + segment->p_offset); |
| - Elf64_Addr size = segment->p_filesz; |
| + + read64(segment->p_offset, be)); |
| + Elf64_Addr size = read32(segment->p_filesz, be); |
| |
| - while (abi_note [0] != 4 || abi_note [1] != 16 |
| - || abi_note [2] != 1 |
| + while (read32(abi_note [0], be) != 4 || read32(abi_note [1], be) != 16 |
| + || read32(abi_note [2], be) != 1 |
| || memcmp (abi_note + 3, "GNU", 4) != 0) |
| { |
| +#undef ROUND |
| #define ROUND(len) (((len) + sizeof (Elf64_Word) - 1) & -sizeof (Elf64_Word)) |
| Elf64_Addr note_size = 3 * sizeof (Elf64_Word) |
| - + ROUND (abi_note[0]) |
| - + ROUND (abi_note[1]); |
| + + ROUND (read32(abi_note[0], be)) |
| + + ROUND (read32(abi_note[1], be)); |
| |
| if (size - 32 < note_size || note_size == 0) |
| { |
| @@ -327,10 +354,10 @@ process_elf_file64 (const char *file_nam |
| if (size == 0) |
| break; |
| |
| - *osversion = (abi_note [4] << 24) | |
| - ((abi_note [5] & 0xff) << 16) | |
| - ((abi_note [6] & 0xff) << 8) | |
| - (abi_note [7] & 0xff); |
| + *osversion = (read32(abi_note [4], be) << 24) | |
| + ((read32(abi_note [5], be) & 0xff) << 16) | |
| + ((read32(abi_note [6], be) & 0xff) << 8) | |
| + (read32(abi_note [7], be) & 0xff); |
| } |
| break; |
| |
| @@ -354,13 +381,13 @@ process_elf_file64 (const char *file_nam |
| |
| /* Find the string table. */ |
| dynamic_strings = NULL; |
| - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; |
| + for (dyn_entry = dynamic_segment; read64(dyn_entry->d_tag, be) != DT_NULL; |
| ++dyn_entry) |
| { |
| check_ptr (dyn_entry); |
| - if (dyn_entry->d_tag == DT_STRTAB) |
| + if (read64(dyn_entry->d_tag, be) == DT_STRTAB) |
| { |
| - dynamic_strings = (char *) (file_contents + dyn_entry->d_un.d_val - loadaddr); |
| + dynamic_strings = (char *) (file_contents + read64(dyn_entry->d_un.d_val, be) - loadaddr); |
| check_ptr (dynamic_strings); |
| break; |
| } |
| @@ -370,15 +397,15 @@ process_elf_file64 (const char *file_nam |
| return 1; |
| |
| /* Now read the DT_NEEDED and DT_SONAME entries. */ |
| - for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL; |
| + for (dyn_entry = dynamic_segment; read64(dyn_entry->d_tag, be) != DT_NULL; |
| ++dyn_entry) |
| { |
| - if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME) |
| + if (read64(dyn_entry->d_tag, be) == DT_NEEDED || read64(dyn_entry->d_tag, be) == DT_SONAME) |
| { |
| - char *name = dynamic_strings + dyn_entry->d_un.d_val; |
| + char *name = dynamic_strings + read64(dyn_entry->d_un.d_val, be); |
| check_ptr (name); |
| |
| - if (dyn_entry->d_tag == DT_NEEDED) |
| + if (read64(dyn_entry->d_tag, be) == DT_NEEDED) |
| { |
| |
| if (*flag == FLAG_ELF) |
| @@ -395,7 +422,7 @@ process_elf_file64 (const char *file_nam |
| } |
| } |
| |
| - else if (dyn_entry->d_tag == DT_SONAME) |
| + else if (read64(dyn_entry->d_tag, be) == DT_SONAME) |
| *soname = xstrdup (name); |
| |
| /* Do we have everything we need? */ |
| Index: ldconfig-native-2.12.1/readlib.c |
| =================================================================== |
| --- ldconfig-native-2.12.1.orig/readlib.c |
| +++ ldconfig-native-2.12.1/readlib.c |
| @@ -169,7 +169,8 @@ process_file (const char *real_file_name |
| ret = 1; |
| } |
| /* Libraries have to be shared object files. */ |
| - else if (elf_header->e_type != ET_DYN) |
| + else if ((elf_header->e_ident[EI_DATA] == ELFDATA2MSB && be16toh(elf_header->e_type) != ET_DYN) || |
| + (elf_header->e_ident[EI_DATA] == ELFDATA2LSB && le16toh(elf_header->e_type) != ET_DYN)) |
| ret = 1; |
| else if (process_elf_file (file_name, lib, flag, osversion, soname, |
| file_contents, statbuf.st_size)) |
| Index: ldconfig-native-2.12.1/cache.c |
| =================================================================== |
| --- ldconfig-native-2.12.1.orig/cache.c |
| +++ ldconfig-native-2.12.1/cache.c |
| @@ -39,6 +39,29 @@ |
| # define N_(msgid) msgid |
| #define _(msg) msg |
| |
| +extern int be; |
| + |
| +static uint16_t write16(uint16_t x, int be) |
| +{ |
| + if (be) |
| + return htobe16(x); |
| + return htole16(x); |
| +} |
| + |
| +static uint32_t write32(uint32_t x, int be) |
| +{ |
| + if (be) |
| + return htobe32(x); |
| + return htole32(x); |
| +} |
| + |
| +static uint64_t write64(uint64_t x, int be) |
| +{ |
| + if (be) |
| + return htobe64(x); |
| + return htole64(x); |
| +} |
| + |
| struct cache_entry |
| { |
| char *lib; /* Library name. */ |
| @@ -279,7 +302,12 @@ save_cache (const char *cache_name) |
| /* Number of normal cache entries. */ |
| int cache_entry_old_count = 0; |
| |
| - for (entry = entries; entry != NULL; entry = entry->next) |
| + if (be) |
| + printf("saving cache in big endian encoding\n"); |
| + else |
| + printf("saving cache in little endian encoding\n"); |
| + |
| + for (entry = entries; entry != NULL; entry = entry->next) |
| { |
| /* Account the final NULs. */ |
| total_strlen += strlen (entry->lib) + strlen (entry->path) + 2; |
| @@ -310,7 +338,7 @@ save_cache (const char *cache_name) |
| memset (file_entries, '\0', sizeof (struct cache_file)); |
| memcpy (file_entries->magic, CACHEMAGIC, sizeof CACHEMAGIC - 1); |
| |
| - file_entries->nlibs = cache_entry_old_count; |
| + file_entries->nlibs = write32(cache_entry_old_count, be); |
| } |
| |
| struct cache_file_new *file_entries_new = NULL; |
| @@ -330,8 +358,8 @@ save_cache (const char *cache_name) |
| memcpy (file_entries_new->version, CACHE_VERSION, |
| sizeof CACHE_VERSION - 1); |
| |
| - file_entries_new->nlibs = cache_entry_count; |
| - file_entries_new->len_strings = total_strlen; |
| + file_entries_new->nlibs = write32(cache_entry_count, be); |
| + file_entries_new->len_strings = write32(total_strlen, be); |
| } |
| |
| /* Pad for alignment of cache_file_new. */ |
| @@ -358,9 +386,9 @@ save_cache (const char *cache_name) |
| /* First the library. */ |
| if (opt_format != 2 && entry->hwcap == 0) |
| { |
| - file_entries->libs[idx_old].flags = entry->flags; |
| + file_entries->libs[idx_old].flags = write32(entry->flags, be); |
| /* XXX: Actually we can optimize here and remove duplicates. */ |
| - file_entries->libs[idx_old].key = str_offset + pad; |
| + file_entries->libs[idx_old].key = write32(str_offset + pad, be); |
| } |
| if (opt_format != 0) |
| { |
| @@ -368,10 +396,10 @@ save_cache (const char *cache_name) |
| not doing so makes the code easier, the string table |
| always begins at the beginning of the the new cache |
| struct. */ |
| - file_entries_new->libs[idx_new].flags = entry->flags; |
| - file_entries_new->libs[idx_new].osversion = entry->osversion; |
| - file_entries_new->libs[idx_new].hwcap = entry->hwcap; |
| - file_entries_new->libs[idx_new].key = str_offset; |
| + file_entries_new->libs[idx_new].flags = write32(entry->flags, be); |
| + file_entries_new->libs[idx_new].osversion = write32(entry->osversion, be); |
| + file_entries_new->libs[idx_new].hwcap = write64(entry->hwcap, be); |
| + file_entries_new->libs[idx_new].key = write32(str_offset, be); |
| } |
| |
| size_t len = strlen (entry->lib) + 1; |
| @@ -379,9 +407,9 @@ save_cache (const char *cache_name) |
| str_offset += len; |
| /* Then the path. */ |
| if (opt_format != 2 && entry->hwcap == 0) |
| - file_entries->libs[idx_old].value = str_offset + pad; |
| + file_entries->libs[idx_old].value = write32(str_offset + pad, be); |
| if (opt_format != 0) |
| - file_entries_new->libs[idx_new].value = str_offset; |
| + file_entries_new->libs[idx_new].value = write32(str_offset, be); |
| len = strlen (entry->path) + 1; |
| str = mempcpy (str, entry->path, len); |
| str_offset += len; |