Rev 9 | Rev 11 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 9 | Rev 10 | ||
---|---|---|---|
Line 122... | Line 122... | ||
122 | #define RECORD_SEP '\x1e' // ASCII record separator |
122 | #define RECORD_SEP '\x1e' // ASCII record separator |
123 | #define RECORD_SEP_STR "\x1e" // ASCII record separator (as string) |
123 | #define RECORD_SEP_STR "\x1e" // ASCII record separator (as string) |
124 | 124 | ||
125 | // macros for accessing ELF files |
125 | // macros for accessing ELF files |
126 | #define ELF_MAGIC_STR "\x7f" "ELF" |
126 | #define ELF_MAGIC_STR "\x7f" "ELF" |
127 | #define ELF_ENDIAN_LITTLE 1 // ELF file is little endian |
127 | #define ELF_ENDIAN_LITTLE 1 // 'endianness' member of an ELF header: ELF file is little endian |
128 | #define ELF_ENDIAN_BIG 2 // ELF file is big endian |
128 | #define ELF_ENDIAN_BIG 2 // 'endianness' member of an ELF header: ELF file is big endian |
- | 129 | #define ELF_MACHINE_X86_64 0x3e // 'instruction_set' member of an ELF header, also used in the IFS startup header: ELF file is for x86_64 processors (62 decimal) |
|
- | 130 | #define ELF_MACHINE_AARCH64 0xb7 // 'instruction_set' member of an ELF header, also used in the IFS startup header: ELF file is for ARM64 processors (183 decimal) |
|
- | 131 | #define ELF_SECTIONTYPE_STRINGTABLE 3 |
|
129 | #define ELF_DT_NULL 0 // marks end of dynamic section |
132 | #define ELF_DT_NULL 0 // marks end of dynamic section |
130 | #define ELF_DT_SONAME 14 // canonical name of shared object |
133 | #define ELF_DT_SONAME 14 // canonical name of shared object |
131 | #define |
134 | #define ELF_GET_NUMERIC(elfhdr,elfstruct,member) ((elfhdr)->u.elf.platform_size == 2 ? /* is it a 64-bit ELF file ? */ \ |
132 | ( \ |
135 | ( \ |
133 | (sizeof ((elfstruct)->u.elf64.member) == 1) || (((elfhdr)->u.elf.endianness == 1) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || (((elfhdr)->u.elf.endianness == 2) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) ? /* single-byte, or same endianness ? */ \ |
136 | (sizeof ((elfstruct)->u.elf64.member) == 1) || (((elfhdr)->u.elf.endianness == 1) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || (((elfhdr)->u.elf.endianness == 2) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) ? /* single-byte, or same endianness ? */ \ |
134 | (elfstruct)->u.elf64.member /* same endianness, or single byte required: don't swap */ \ |
137 | (elfstruct)->u.elf64.member /* same endianness, or single byte required: don't swap */ \ |
135 | : /* else */ \ |
138 | : /* else */ \ |
136 | (sizeof ((elfstruct)->u.elf64.member) == 8 ? __builtin_bswap64 ((elfstruct)->u.elf64.member) : (sizeof ((elfstruct)->u.elf64.member) == 4 ? __builtin_bswap32 ((elfstruct)->u.elf64.member) : __builtin_bswap16 ((elfstruct)->u.elf64.member))) /* different endianness: swap */ \ |
139 | (sizeof ((elfstruct)->u.elf64.member) == 8 ? __builtin_bswap64 ((elfstruct)->u.elf64.member) : (sizeof ((elfstruct)->u.elf64.member) == 4 ? __builtin_bswap32 ((elfstruct)->u.elf64.member) : __builtin_bswap16 ((elfstruct)->u.elf64.member))) /* different endianness: swap */ \ |
Line 141... | Line 144... | ||
141 | (elfstruct)->u.elf32.member /* same endianness, or single byte required: don't swap */ \ |
144 | (elfstruct)->u.elf32.member /* same endianness, or single byte required: don't swap */ \ |
142 | : /* else */ \ |
145 | : /* else */ \ |
143 | (sizeof ((elfstruct)->u.elf32.member) == 4 ? __builtin_bswap32 ((elfstruct)->u.elf32.member) : __builtin_bswap16 ((elfstruct)->u.elf32.member)) /* different endianness: swap */ \ |
146 | (sizeof ((elfstruct)->u.elf32.member) == 4 ? __builtin_bswap32 ((elfstruct)->u.elf32.member) : __builtin_bswap16 ((elfstruct)->u.elf32.member)) /* different endianness: swap */ \ |
144 | ) \ |
147 | ) \ |
145 | ) // this macro supports 32- and 64-bit ELF files in low and big endianness transparently |
148 | ) // this macro supports 32- and 64-bit ELF files in low and big endianness transparently |
- | 149 | #define ELF_SET_NUMERIC(elfhdr,elfstruct,member,data) ((elfhdr)->u.elf.platform_size == 2 ? /* is it a 64-bit ELF file ? */ \ |
|
- | 150 | ((elfstruct)->u.elf64.member = ( \ |
|
- | 151 | (sizeof ((elfstruct)->u.elf64.member) == 1) || (((elfhdr)->u.elf.endianness == 1) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || (((elfhdr)->u.elf.endianness == 2) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) ? /* single-byte, or same endianness ? */ \ |
|
- | 152 | (sizeof ((elfstruct)->u.elf64.member) == 8 ? (uint64_t) ((data)) : (sizeof ((elfstruct)->u.elf64.member) == 4 ? (uint32_t) ((data)) : (sizeof ((elfstruct)->u.elf64.member) == 2 ? (uint16_t) ((data)) : (uint8_t) ((data))))) /* same endianness, or single byte required: don't swap */ \ |
|
- | 153 | : /* else */ \ |
|
- | 154 | (sizeof ((elfstruct)->u.elf64.member) == 8 ? __builtin_bswap64 ((data)) : (sizeof ((elfstruct)->u.elf64.member) == 4 ? __builtin_bswap32 ((data)) : __builtin_bswap16 ((data)))) /* different endianness: swap */ \ |
|
- | 155 | )) \ |
|
- | 156 | : /* else poke at 32-bit ELF */ \ |
|
- | 157 | ((elfstruct)->u.elf32.member = ( \ |
|
- | 158 | (sizeof ((elfstruct)->u.elf32.member) == 1) || (((elfhdr)->u.elf.endianness == 1) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || (((elfhdr)->u.elf.endianness == 2) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) ? /* single-byte, or same endianness ? */ \ |
|
- | 159 | (sizeof ((elfstruct)->u.elf64.member) == 4 ? (uint32_t) ((data)) : (sizeof ((elfstruct)->u.elf64.member) == 2 ? (uint16_t) ((data)) : (uint8_t) ((data)))) /* same endianness, or single byte required: don't swap */ \ |
|
- | 160 | : /* else */ \ |
|
- | 161 | (sizeof ((elfstruct)->u.elf32.member) == 4 ? __builtin_bswap32 ((data)) : __builtin_bswap16 ((data))) /* different endianness: swap */ \ |
|
- | 162 | )) \ |
|
- | 163 | ) // this macro supports 32- and 64-bit ELF files in low and big endianness transparently |
|
146 | #define |
164 | #define ELF_GET_STRING(elfhdr,elfstruct,member) ((elfhdr)->u.elf.platform_size == 2 ? (elfstruct)->u.elf64.member : (elfstruct)->u.elf32.member) // this macro supports 32- and 64-bit ELF files transparently |
- | 165 | #define ELF_SET_STRING(elfhdr,elfstruct,member,data,len) memcpy (((elfhdr)->u.elf.platform_size == 2 ? (elfstruct)->u.elf64.member : (elfstruct)->u.elf32.member), (data), (len)) // this macro supports 32- and 64-bit ELF files transparently |
|
147 | #define ELF_STRUCT_SIZE(elfhdr,elfstruct) ((elfhdr)->u.elf.platform_size == 2 ? sizeof ((elfstruct)->u.elf64) : sizeof ((elfstruct)->u.elf32)) // this macro supports 32- and 64-bit ELF files transparently |
166 | #define ELF_STRUCT_SIZE(elfhdr,elfstruct) ((elfhdr)->u.elf.platform_size == 2 ? sizeof ((elfstruct)->u.elf64) : sizeof ((elfstruct)->u.elf32)) // this macro supports 32- and 64-bit ELF files transparently |
- | 167 | ||
- | 168 | ||
148 | 169 | ||
149 | #define WILL_BE_FILLED_LATER 0xbaadf00d |
170 | #define WILL_BE_FILLED_LATER 0xbaadf00d |
150 | 171 | ||
151 | 172 | ||
152 | // bitmapped flags used in the flags1 member of the startup header |
173 | // bitmapped flags used in the flags1 member of the startup header |
Line 157... | Line 178... | ||
157 | //#define STARTUP_HDR_FLAGS1_COMPRESS_NONE 0x00 |
178 | //#define STARTUP_HDR_FLAGS1_COMPRESS_NONE 0x00 |
158 | //#define STARTUP_HDR_FLAGS1_COMPRESS_ZLIB 0x04 |
179 | //#define STARTUP_HDR_FLAGS1_COMPRESS_ZLIB 0x04 |
159 | //#define STARTUP_HDR_FLAGS1_COMPRESS_LZO 0x08 |
180 | //#define STARTUP_HDR_FLAGS1_COMPRESS_LZO 0x08 |
160 | //#define STARTUP_HDR_FLAGS1_COMPRESS_UCL 0x0c |
181 | //#define STARTUP_HDR_FLAGS1_COMPRESS_UCL 0x0c |
161 | #define STARTUP_HDR_FLAGS1_TRAILER_V2 (1 << 5) // if set, then a struct startup_trailer_v2 follows the startup. If the image is compressed, then the compressed imagefs is followed by a struct image_trailer_v2 |
182 | #define STARTUP_HDR_FLAGS1_TRAILER_V2 (1 << 5) // if set, then a struct startup_trailer_v2 follows the startup. If the image is compressed, then the compressed imagefs is followed by a struct image_trailer_v2 |
162 | - | ||
163 | - | ||
164 | #define STARTUP_HDR_MACHINE_X86_64 0x3e |
- | |
165 | #define STARTUP_HDR_MACHINE_AARCH64 0xb7 |
- | |
166 | 183 | ||
167 | 184 | ||
168 | // bitmapped flags used in the flags member of the image header |
185 | // bitmapped flags used in the flags member of the image header |
169 | #define IMAGE_FLAGS_BIGENDIAN (1 << 0) // header, trailer, dirents in big-endian format |
186 | #define IMAGE_FLAGS_BIGENDIAN (1 << 0) // header, trailer, dirents in big-endian format |
170 | #define IMAGE_FLAGS_READONLY (1 << 1) // do not try to write to image (rom/flash) |
187 | #define IMAGE_FLAGS_READONLY (1 << 1) // do not try to write to image (rom/flash) |
Line 423... | Line 440... | ||
423 | { |
440 | { |
424 | union __attribute__((packed)) |
441 | union __attribute__((packed)) |
425 | { |
442 | { |
426 | struct __attribute__((packed)) |
443 | struct __attribute__((packed)) |
427 | { |
444 | { |
428 | uint8_t magic[4]; // offset 0: " |
445 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
429 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
446 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
430 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
447 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
431 | uint8_t header_version; // offset 6: typically 1 |
448 | uint8_t header_version; // offset 6: typically 1 |
432 | uint8_t os_abi; // offset 7: 0 = SysV, 1 = HP/UX, 2 = NetBSD, 3 = Linux, 4 = GNU/Hurd, 6 = Solaris, 7 = AIX, 8 = IRIX, 9 = FreeBSD, 10 = Tru64, 11 = Novell, 12 = OpenBSD, 13 = OpenVMS, 14 = NonStop kernel, 15 = AROS, 16 = FenixOS, 17 = Nuxi CloudABI, 18 = OpenVOS |
449 | uint8_t os_abi; // offset 7: 0 = SysV, 1 = HP/UX, 2 = NetBSD, 3 = Linux, 4 = GNU/Hurd, 6 = Solaris, 7 = AIX, 8 = IRIX, 9 = FreeBSD, 10 = Tru64, 11 = Novell, 12 = OpenBSD, 13 = OpenVMS, 14 = NonStop kernel, 15 = AROS, 16 = FenixOS, 17 = Nuxi CloudABI, 18 = OpenVOS |
433 | uint8_t spare[8]; // offset 8: zeroes |
450 | uint8_t spare[8]; // offset 8: zeroes |
434 | uint16_t type; // offset 16: 1 = relocatable, 2 = executable, 3 = shared, 4 = core dump |
451 | uint16_t type; // offset 16: 1 = relocatable, 2 = executable, 3 = shared, 4 = core dump |
435 | uint16_t instruction_set; // offset 18: 2 = Sparc, 3 = i386, 8 = MIPS, 20 = PowerPC, 40 = ARM, 42 = SuperH, 50 = IA-64, 62 = x86_64, 183 = AArch64, 243 = RISC-V |
452 | uint16_t instruction_set; // offset 18: 2 = Sparc, 3 = i386, 8 = MIPS, 20 = PowerPC, 40 = ARM, 42 = SuperH, 50 = IA-64, 62 = x86_64, 183 = AArch64, 243 = RISC-V |
436 | uint32_t elf_version; // offset 20: typically 1 |
453 | uint32_t elf_version; // offset 20: typically 1 |
437 | } elf; |
454 | } elf; |
438 | struct __attribute__((packed)) |
455 | struct __attribute__((packed)) // size == 52 |
439 | { |
456 | { |
440 | uint8_t magic[4]; // offset 0: " |
457 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
441 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
458 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
442 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
459 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
443 | uint8_t header_version; // offset 6: typically 1 |
460 | uint8_t header_version; // offset 6: typically 1 |
444 | uint8_t os_abi; // offset 7: 0 = SysV, 1 = HP/UX, 2 = NetBSD, 3 = Linux, 4 = GNU/Hurd, 6 = Solaris, 7 = AIX, 8 = IRIX, 9 = FreeBSD, 10 = Tru64, 11 = Novell, 12 = OpenBSD, 13 = OpenVMS, 14 = NonStop kernel, 15 = AROS, 16 = FenixOS, 17 = Nuxi CloudABI, 18 = OpenVOS |
461 | uint8_t os_abi; // offset 7: 0 = SysV, 1 = HP/UX, 2 = NetBSD, 3 = Linux, 4 = GNU/Hurd, 6 = Solaris, 7 = AIX, 8 = IRIX, 9 = FreeBSD, 10 = Tru64, 11 = Novell, 12 = OpenBSD, 13 = OpenVMS, 14 = NonStop kernel, 15 = AROS, 16 = FenixOS, 17 = Nuxi CloudABI, 18 = OpenVOS |
445 | uint8_t spare[8]; // offset 8: zeroes |
462 | uint8_t spare[8]; // offset 8: zeroes |
Line 454... | Line 471... | ||
454 | uint16_t program_header_item_size; // offset 42: size of an entry in the program header table |
471 | uint16_t program_header_item_size; // offset 42: size of an entry in the program header table |
455 | uint16_t program_header_table_len; // offset 44: number of entries in the program header table |
472 | uint16_t program_header_table_len; // offset 44: number of entries in the program header table |
456 | uint16_t section_header_item_size; // offset 46: size of an entry in the section header table |
473 | uint16_t section_header_item_size; // offset 46: size of an entry in the section header table |
457 | uint16_t section_header_table_len; // offset 48: number of entries in the section header table |
474 | uint16_t section_header_table_len; // offset 48: number of entries in the section header table |
458 | uint16_t section_header_names_idx; // offset 50: index of the entry in the section header table that contains the section names |
475 | uint16_t section_header_names_idx; // offset 50: index of the entry in the section header table that contains the section names |
459 | } elf32; |
476 | } elf32; // size == 52 |
460 | struct __attribute__((packed)) |
477 | struct __attribute__((packed)) // size == 64 |
461 | { |
478 | { |
462 | uint8_t magic[4]; // offset 0: " |
479 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
463 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
480 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
464 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
481 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
465 | uint8_t header_version; // offset 6: typically 1 |
482 | uint8_t header_version; // offset 6: typically 1 |
466 | uint8_t os_abi; // offset 7: 0 = SysV, 1 = HP/UX, 2 = NetBSD, 3 = Linux, 4 = GNU/Hurd, 6 = Solaris, 7 = AIX, 8 = IRIX, 9 = FreeBSD, 10 = Tru64, 11 = Novell, 12 = OpenBSD, 13 = OpenVMS, 14 = NonStop kernel, 15 = AROS, 16 = FenixOS, 17 = Nuxi CloudABI, 18 = OpenVOS |
483 | uint8_t os_abi; // offset 7: 0 = SysV, 1 = HP/UX, 2 = NetBSD, 3 = Linux, 4 = GNU/Hurd, 6 = Solaris, 7 = AIX, 8 = IRIX, 9 = FreeBSD, 10 = Tru64, 11 = Novell, 12 = OpenBSD, 13 = OpenVMS, 14 = NonStop kernel, 15 = AROS, 16 = FenixOS, 17 = Nuxi CloudABI, 18 = OpenVOS |
467 | uint8_t spare[8]; // offset 8: zeroes |
484 | uint8_t spare[8]; // offset 8: zeroes |
Line 476... | Line 493... | ||
476 | uint16_t program_header_item_size; // offset 54: size of an entry in the program header table |
493 | uint16_t program_header_item_size; // offset 54: size of an entry in the program header table |
477 | uint16_t program_header_table_len; // offset 56: number of entries in the program header table |
494 | uint16_t program_header_table_len; // offset 56: number of entries in the program header table |
478 | uint16_t section_header_item_size; // offset 58: size of an entry in the section header table |
495 | uint16_t section_header_item_size; // offset 58: size of an entry in the section header table |
479 | uint16_t section_header_table_len; // offset 60: number of entries in the section header table |
496 | uint16_t section_header_table_len; // offset 60: number of entries in the section header table |
480 | uint16_t section_header_names_idx; // offset 62: index of the entry in the section header table that contains the section names |
497 | uint16_t section_header_names_idx; // offset 62: index of the entry in the section header table that contains the section names |
481 | } elf64; |
498 | } elf64; // size == 64 |
482 | } u; |
499 | } u; |
483 | } elf_header_t; |
500 | } elf_header_t; |
- | 501 | ||
- | 502 | ||
- | 503 | // Executable and Linkable Format program header structure type definition |
|
- | 504 | typedef struct __attribute__((packed)) elf_program_header_s |
|
- | 505 | { |
|
- | 506 | union __attribute__((packed)) |
|
- | 507 | { |
|
- | 508 | struct __attribute__((packed)) |
|
- | 509 | { |
|
- | 510 | uint32_t segment_type; // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template) |
|
- | 511 | } elf; |
|
- | 512 | struct __attribute__((packed)) // size == 32 |
|
- | 513 | { |
|
- | 514 | uint32_t segment_type; // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template) |
|
- | 515 | uint32_t file_offset; // offset 4: file offset of this segment |
|
- | 516 | uint32_t virtual_addr; // offset 8: virtual address where this segment should be mapped in memory |
|
- | 517 | uint32_t physical_addr; // offset 12: on systems where this is relevant, PHYSICAL address where this segment should be mapped in memory |
|
- | 518 | uint32_t size_in_file; // offset 16: size of this segment in the ELF file (may be zero) |
|
- | 519 | uint32_t size_in_memory; // offset 20: size of this segment in memory (may be zero) |
|
- | 520 | uint32_t segment_flags; // offset 24: bitmap of segment flags (1: executable, 2: writable, 4: readable) |
|
- | 521 | uint32_t alignment; // offset 28: memory alignment (0 or 1 mean non alignment, else must be a power of 2 where virtual_addr == file_offset % alignment) |
|
- | 522 | } elf32; // size == 32 |
|
- | 523 | struct __attribute__((packed)) // size == 56 |
|
- | 524 | { |
|
- | 525 | uint32_t segment_type; // offset 0: type of segment (0: unused table entry, 1: loadable, 2: dynamic linking information, 3: interpreter information, 4: auxiliary information, 5: reserved, 6: this very segment, 7: TLS template) |
|
- | 526 | uint32_t segment_flags; // offset 4: bitmap of segment flags (1: executable, 2: writable, 4: readable) |
|
- | 527 | uint64_t file_offset; // offset 8: file offset of this segment |
|
- | 528 | uint64_t virtual_addr; // offset 16: virtual address where this segment should be mapped in memory |
|
- | 529 | uint64_t physical_addr; // offset 24: on systems where this is relevant, PHYSICAL address where this segment should be mapped in memory |
|
- | 530 | uint64_t size_in_file; // offset 32: size of this segment in the ELF file (may be zero) |
|
- | 531 | uint64_t size_in_memory; // offset 40: size of this segment in memory (may be zero) |
|
- | 532 | uint64_t alignment; // offset 48: memory alignment (0 or 1 mean non alignment, else must be a power of 2 where virtual_addr == file_offset % alignment) |
|
- | 533 | } elf64; // size == 56 |
|
- | 534 | } u; |
|
- | 535 | } elf_program_header_t; |
|
484 | 536 | ||
485 | 537 | ||
486 | // Executable and Linkable Format section header structure type definition |
538 | // Executable and Linkable Format section header structure type definition |
487 | typedef struct __attribute__((packed)) elf_section_header_s |
539 | typedef struct __attribute__((packed)) elf_section_header_s |
488 | { |
540 | { |
489 | union __attribute__((packed)) |
541 | union __attribute__((packed)) |
490 | { |
542 | { |
491 | struct __attribute__((packed)) |
543 | struct __attribute__((packed)) // size == 40 |
492 | { |
544 | { |
493 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
545 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
494 | uint32_t type; // offset 4: |
546 | uint32_t type; // offset 4: |
495 | uint32_t flags; // offset 8: |
547 | uint32_t flags; // offset 8: |
496 | uint32_t virtual_addr; // offset 12: address in virtual memory where this section may be loaded |
548 | uint32_t virtual_addr; // offset 12: address in virtual memory where this section may be loaded |
Line 498... | Line 550... | ||
498 | uint32_t size; // offset 20: size of this section |
550 | uint32_t size; // offset 20: size of this section |
499 | uint32_t linked_index; // offset 24: optional section index of an associated section |
551 | uint32_t linked_index; // offset 24: optional section index of an associated section |
500 | uint32_t info; // offset 28: optional extra information |
552 | uint32_t info; // offset 28: optional extra information |
501 | uint32_t alignment; // offset 32: required memory alignment (must be a power of 2) |
553 | uint32_t alignment; // offset 32: required memory alignment (must be a power of 2) |
502 | uint32_t entry_size; // offset 36: for table-like sections, size of an element in the table |
554 | uint32_t entry_size; // offset 36: for table-like sections, size of an element in the table |
503 | } elf32; |
555 | } elf32; // size == 40 |
504 | struct __attribute__((packed)) |
556 | struct __attribute__((packed)) // size == 64 |
505 | { |
557 | { |
506 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
558 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
507 | uint32_t type; // offset 4: |
559 | uint32_t type; // offset 4: |
508 | uint64_t flags; // offset 8: |
560 | uint64_t flags; // offset 8: |
509 | uint64_t virtual_addr; // offset 16: address in virtual memory where this section may be loaded |
561 | uint64_t virtual_addr; // offset 16: address in virtual memory where this section may be loaded |
Line 511... | Line 563... | ||
511 | uint64_t size; // offset 32: size of this section |
563 | uint64_t size; // offset 32: size of this section |
512 | uint32_t linked_index; // offset 40: optional section index of an associated section |
564 | uint32_t linked_index; // offset 40: optional section index of an associated section |
513 | uint32_t info; // offset 44: optional extra information |
565 | uint32_t info; // offset 44: optional extra information |
514 | uint64_t alignment; // offset 48: required memory alignment (must be a power of 2) |
566 | uint64_t alignment; // offset 48: required memory alignment (must be a power of 2) |
515 | uint64_t entry_size; // offset 56: for table-like sections, size of an element in the table |
567 | uint64_t entry_size; // offset 56: for table-like sections, size of an element in the table |
516 | } elf64; |
568 | } elf64; // size == 64 |
517 | } u; |
569 | } u; |
518 | } elf_section_header_t; |
570 | } elf_section_header_t; |
519 | 571 | ||
520 | 572 | ||
521 | // Executable and Linkable Format dynamic section entry structure type definition |
573 | // Executable and Linkable Format dynamic section entry structure type definition |
522 | typedef struct __attribute__((packed)) elf_dynamic_section_entry_s |
574 | typedef struct __attribute__((packed)) elf_dynamic_section_entry_s |
523 | { |
575 | { |
524 | union __attribute__((packed)) |
576 | union __attribute__((packed)) |
525 | { |
577 | { |
526 | struct __attribute__(( |
578 | struct __attribute__((packed)) // size == 8 |
527 | { |
579 | { |
528 | int32_t tag; // dynamic entry type (one of ELF_DT_xxx #defines) |
580 | int32_t tag; // dynamic entry type (one of ELF_DT_xxx #defines) |
529 | union |
581 | union |
530 | { |
582 | { |
531 | uint32_t as_integer; // value as integer |
583 | uint32_t as_integer; // value as integer |
532 | uint32_t as_pointer; // value as address |
584 | uint32_t as_pointer; // value as address |
533 | } value; |
585 | } value; |
534 | } elf32; |
586 | } elf32; // size == 8 |
535 | struct __attribute__((packed)) |
587 | struct __attribute__((packed)) // size == 16 |
536 | { |
588 | { |
537 | int64_t tag; // dynamic entry type (one of ELF_DT_xxx #defines) |
589 | int64_t tag; // dynamic entry type (one of ELF_DT_xxx #defines) |
538 | union |
590 | union |
539 | { |
591 | { |
540 | uint64_t as_integer; // value as intege |
592 | uint64_t as_integer; // value as intege |
541 | uint64_t as_pointer; // value as address |
593 | uint64_t as_pointer; // value as address |
542 | } value; |
594 | } value; |
543 | } elf64; |
595 | } elf64; // size == 16 |
544 | } u; |
596 | } u; |
545 | } elf_dynamic_section_entry_t; |
597 | } elf_dynamic_section_entry_t; |
546 | 598 | ||
547 | 599 | ||
548 | #ifdef _MSC_VER |
600 | #ifdef _MSC_VER |
Line 561... | Line 613... | ||
561 | uint32_t mtime_for_inline_files; // same as above but only for files that don't exist on the build host (i.e. files with an explicit content blob) |
613 | uint32_t mtime_for_inline_files; // same as above but only for files that don't exist on the build host (i.e. files with an explicit content blob) |
562 | char prefix[MAXPATHLEN]; // install path (e.g. "proc/boot") |
614 | char prefix[MAXPATHLEN]; // install path (e.g. "proc/boot") |
563 | bool should_follow_symlinks; // follow symlinks |
615 | bool should_follow_symlinks; // follow symlinks |
564 | bool should_autosymlink_dylib; // dynamic libraries should be written under their official SONAME and a named symlink be created pointing at them |
616 | bool should_autosymlink_dylib; // dynamic libraries should be written under their official SONAME and a named symlink be created pointing at them |
565 | bool is_compiled_bootscript; // entry has [+script] attribute |
617 | bool is_compiled_bootscript; // entry has [+script] attribute |
- | 618 | int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx) |
|
566 | char search[10 * MAXPATHLEN]; // binary search path (the default one will be constructed at startup) |
619 | char search[10 * MAXPATHLEN]; // binary search path (the default one will be constructed at startup) |
567 | 620 | ||
568 | uint8_t *data; |
621 | uint8_t *data; |
569 | size_t datalen; |
622 | size_t datalen; |
570 | } parms_t; |
623 | } parms_t; |
Line 604... | Line 657... | ||
604 | static void hex_fprintf (FILE *fp, const uint8_t *data, size_t data_size, int howmany_columns, const char *fmt, ...); // hexdump-style formatted output to a file stream (which may be stdout/stderr) |
657 | static void hex_fprintf (FILE *fp, const uint8_t *data, size_t data_size, int howmany_columns, const char *fmt, ...); // hexdump-style formatted output to a file stream (which may be stdout/stderr) |
605 | static char *binary (const uint8_t x, char char_for_zero, char char_for_one); // returns the binary representation of byte 'x' as a string |
658 | static char *binary (const uint8_t x, char char_for_zero, char char_for_one); // returns the binary representation of byte 'x' as a string |
606 | static char *describe_uint8 (const uint8_t x, const char *bitwise_stringdescs[8]); // returns the ORed description of byte 'x' according to the description strings for each bit |
659 | static char *describe_uint8 (const uint8_t x, const char *bitwise_stringdescs[8]); // returns the ORed description of byte 'x' according to the description strings for each bit |
607 | static char *read_filecontents (const char *pathname, const char *search_path, uint8_t **databuf, size_t *datalen); // locates pathname among MKIFS_PATH, reads it, places its contents in a buffer (caller frees) and returns a pointer to the resolved pathname (static string) |
660 | static char *read_filecontents (const char *pathname, const char *search_path, uint8_t **databuf, size_t *datalen); // locates pathname among MKIFS_PATH, reads it, places its contents in a buffer (caller frees) and returns a pointer to the resolved pathname (static string) |
608 | static int fwrite_filecontents (const char *pathname, FILE *fp); // dumps the contents of pathname into fp |
661 | static int fwrite_filecontents (const char *pathname, FILE *fp); // dumps the contents of pathname into fp |
- | 662 | static int relative_offset_of_in (const char *name, const char *string_table, const size_t table_len); // returns the relative offset of a particular string in a string table |
|
- | 663 | static elf_section_header_t *elf_get_section_header_by_name (const elf_header_t *elf, const char *section_name); // get a pointer to a named section header in an ELF file |
|
609 | static size_t fwrite_fsentry (const fsentry_t *fsentry, FILE *fp); // writes the given filesystem entry into fp (without its contents) |
664 | static size_t fwrite_fsentry (const fsentry_t *fsentry, FILE *fp); // writes the given filesystem entry into fp (without its contents) |
610 | static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname); // stack up a new filesystem entry |
665 | static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname); // stack up a new filesystem entry |
611 | static int fsentry_compare_pathnames_cb (const void *a, const void *b); // qsort() comparison callback that sorts filesystem entries by pathnames |
666 | static int fsentry_compare_pathnames_cb (const void *a, const void *b); // qsort() comparison callback that sorts filesystem entries by pathnames |
612 | static void update_MKIFS_PATH (const char *processor); |
667 | static void update_MKIFS_PATH (const char *processor); |
613 | static int dump_ifs_info (const char *ifs_pathname); // dumps detailed info about a particular IFS file on the standard output, returns 0 on success and >0 on error |
668 | static int dump_ifs_info (const char *ifs_pathname, bool want_everything); // dumps detailed info about a particular IFS file on the standard output, returns 0 on success and >0 on error |
614 | 669 | ||
615 | 670 | ||
616 | static void sha512_private_transform (SHA512_CTX *context, const uint64_t *data) |
671 | static void sha512_private_transform (SHA512_CTX *context, const uint64_t *data) |
617 | { |
672 | { |
618 | // logical functions used in SHA-384 and SHA-512 |
673 | // logical functions used in SHA-384 and SHA-512 |
Line 1057... | Line 1112... | ||
1057 | 1112 | ||
1058 | ret = (int) fwrite (blob_buffer, 1, blob_size, fp); |
1113 | ret = (int) fwrite (blob_buffer, 1, blob_size, fp); |
1059 | fflush (fp); // force flush to disk, because the C stream API is *buffered* |
1114 | fflush (fp); // force flush to disk, because the C stream API is *buffered* |
1060 | free (blob_buffer); |
1115 | free (blob_buffer); |
1061 | return (ret); |
1116 | return (ret); |
- | 1117 | } |
|
- | 1118 | ||
- | 1119 | ||
- | 1120 | static int relative_offset_of_in (const char *name, const char *string_table, const size_t table_len) |
|
- | 1121 | { |
|
- | 1122 | int name_len = (int) strlen (name) + 1; |
|
- | 1123 | WELLMANNERED_ASSERT (name_len < table_len, "bad call (name longer than string table)"); |
|
- | 1124 | for (int idx = 0; idx <= table_len - name_len; idx++) |
|
- | 1125 | if (memcmp (&string_table[idx], name, name_len) == 0) |
|
- | 1126 | return (idx); |
|
- | 1127 | WELLMANNERED_ASSERT (false, "bad call (name '%s' not found in string table)", name); |
|
- | 1128 | return (0); |
|
- | 1129 | } |
|
- | 1130 | ||
- | 1131 | ||
- | 1132 | static elf_section_header_t *elf_get_section_header_by_name (const elf_header_t *elf, const char *section_name) |
|
- | 1133 | { |
|
- | 1134 | elf_section_header_t *shdr_shstrtab; // section header of the section header strings table |
|
- | 1135 | elf_section_header_t *shdr; |
|
- | 1136 | size_t table_count; |
|
- | 1137 | size_t table_index; |
|
- | 1138 | char *shstrtab; // section header strings table |
|
- | 1139 | char *name; |
|
- | 1140 | ||
- | 1141 | shdr_shstrtab = (elf_section_header_t *) ((uint8_t *) elf + ELF_GET_NUMERIC (elf, elf, section_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, section_header_item_size) * ELF_GET_NUMERIC (elf, elf, section_header_names_idx)); // quick access to section header for the section that contains the section names |
|
- | 1142 | shstrtab = ((uint8_t *) elf + ELF_GET_NUMERIC (elf, shdr_shstrtab, file_offset)); // locate the start of the strings table that contains the section names |
|
- | 1143 | ||
- | 1144 | // cycle through the sections table |
|
- | 1145 | table_count = ELF_GET_NUMERIC (elf, elf, section_header_table_len); |
|
- | 1146 | for (table_index = 0; table_index < table_count; table_index++) |
|
- | 1147 | { |
|
- | 1148 | shdr = (elf_section_header_t *) ((uint8_t *) elf + ELF_GET_NUMERIC (elf, elf, section_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, section_header_item_size) * table_index); // quick access to section header |
|
- | 1149 | name = &shstrtab[ELF_GET_NUMERIC (elf, shdr, name_offset)]; // peek at its name |
|
- | 1150 | if (strcmp (name, section_name) == 0) |
|
- | 1151 | return (shdr); // if found, return a pointer to this section header |
|
- | 1152 | } |
|
- | 1153 | ||
- | 1154 | return (NULL); // section not found |
|
1062 | } |
1155 | } |
1063 | 1156 | ||
1064 | 1157 | ||
1065 | static size_t fwrite_fsentry (const fsentry_t *fsentry, FILE *fp) |
1158 | static size_t fwrite_fsentry (const fsentry_t *fsentry, FILE *fp) |
1066 | { |
1159 | { |
Line 1143... | Line 1236... | ||
1143 | } |
1236 | } |
1144 | 1237 | ||
1145 | 1238 | ||
1146 | static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname) |
1239 | static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname) |
1147 | { |
1240 | { |
- | 1241 | #define ADD_NAME_TO_STRINGTABLE(name,pstrtab,pstrtablen) do { \ |
|
- | 1242 | name_len = strlen ((name)) + 1; \ |
|
- | 1243 | reallocated_ptr = realloc (*(pstrtab), *(pstrtablen) + name_len); \ |
|
- | 1244 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); \ |
|
- | 1245 | *(pstrtab) = reallocated_ptr; \ |
|
- | 1246 | memcpy (&(*pstrtab)[*(pstrtablen)], (name), name_len); \ |
|
- | 1247 | *(pstrtablen) += name_len; \ |
|
- | 1248 | } while (0) |
|
- | 1249 | ||
1148 | static thread_local char candidate_pathname[1024]; |
1250 | static thread_local char candidate_pathname[1024]; |
1149 | static int inode_count = 0; // will be preincremented each time this function is called |
1251 | static int inode_count = 0; // will be preincremented each time this function is called |
1150 | 1252 | ||
1151 | const char *original_stored_pathname = NULL; |
1253 | const char *original_stored_pathname = NULL; |
1152 | const elf_dynamic_section_entry_t *dynamic_entry; // dynamic section entry |
1254 | const elf_dynamic_section_entry_t *dynamic_entry; // dynamic section entry |
1153 | const elf_section_header_t *shdr_shstr; // section headers strings (containing ELF sections names) |
- | |
1154 | const elf_section_header_t *shdr_dynstr; // dynamic strings |
1255 | const elf_section_header_t *shdr_dynstr; // dynamic strings |
1155 | const elf_section_header_t *shdr_dynamic; // dynamic section |
1256 | const elf_section_header_t *shdr_dynamic; // dynamic section |
1156 | const elf_section_header_t *shdr; |
1257 | const elf_section_header_t *shdr; |
- | 1258 | elf_section_header_t *new_shdr; |
|
- | 1259 | size_t new_qnxinfo_shdr_offset; |
|
- | 1260 | size_t new_debuglink_shdr_offset; |
|
- | 1261 | size_t new_qnxusage_shdr_offset; |
|
- | 1262 | size_t new_buildid_shdr_offset; |
|
- | 1263 | size_t new_shstrtab_shdr_offset; |
|
- | 1264 | elf_program_header_t *phdr; |
|
1157 | const char *canonical_dylib_name; |
1265 | const char *canonical_dylib_name; |
1158 | const char *elf_section_name; |
- | |
1159 | const char *dynamic_strings; // strings table of the ".dynamic" section |
1266 | const char *dynamic_strings; // strings table of the ".dynamic" section |
1160 | const char *shtable_strings; // strings table of the section headers table |
- | |
1161 | const char *last_dirsep; |
1267 | const char *last_dirsep; |
1162 |
|
1268 | elf_header_t *elf; |
- | 1269 | uint8_t *new_shdr_table = NULL; // mallocated |
|
- | 1270 | size_t new_shdr_tablesize = 0; |
|
- | 1271 | uint8_t *elfsection_qnxinfo_data = NULL; // mallocated |
|
- | 1272 | size_t elfsection_qnxinfo_size = 0; |
|
- | 1273 | uint8_t *elfsection_qnxusage_data = NULL; // mallocated |
|
- | 1274 | size_t elfsection_qnxusage_size = 0; |
|
- | 1275 | uint8_t *elfsection_debuglink_data = NULL; // mallocated |
|
- | 1276 | size_t elfsection_debuglink_size = 0; |
|
- | 1277 | uint8_t *elfsection_buildid_data = NULL; // mallocated |
|
- | 1278 | size_t elfsection_buildid_size = 0; |
|
- | 1279 | uint8_t *elfsection_shstrtab_data = NULL; // mallocated |
|
- | 1280 | size_t elfsection_shstrtab_size = 0; |
|
1163 | char *resolved_pathname; |
1281 | char *resolved_pathname; |
1164 | void *reallocated_ptr; |
1282 | void *reallocated_ptr; |
1165 | void *old_data; |
1283 | void *old_data; |
1166 | struct stat stat_buf; |
1284 | struct stat stat_buf; |
- | 1285 | size_t new_shdrtable_offset; |
|
- | 1286 | size_t end_padding_offset; |
|
1167 | size_t table_index; |
1287 | size_t table_index; |
1168 | size_t table_count; |
1288 | size_t table_count; |
1169 | //uint32_t mtime = (entry_parms->m(uint32_t) time (NULL); |
- | |
1170 |
|
1289 | size_t name_len; |
1171 | fsentry_t *fsentry; |
1290 | fsentry_t *fsentry; |
1172 | 1291 | ||
1173 | if (S_ISDIR (entry_parms->st_mode)) // are we storing a directory ? |
1292 | if (S_ISDIR (entry_parms->st_mode)) // are we storing a directory ? |
1174 | { |
1293 | { |
1175 | fprintf (stderr, "directory: ino 0x%x uid %d gid %d mode 0%o path \"%s\"\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname); |
1294 | fprintf (stderr, "directory: ino 0x%x uid %d gid %d mode 0%o path \"%s\"\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname); |
Line 1180... | Line 1299... | ||
1180 | { |
1299 | { |
1181 | // HACK: for now just consider the kernel as a binary blob |
1300 | // HACK: for now just consider the kernel as a binary blob |
1182 | // FIXME: reimplement properly |
1301 | // FIXME: reimplement properly |
1183 | sprintf (candidate_pathname, "%s/procnto-smp-instr", entry_parms->prefix); // fix the entry name |
1302 | sprintf (candidate_pathname, "%s/procnto-smp-instr", entry_parms->prefix); // fix the entry name |
1184 | stored_pathname = candidate_pathname; |
1303 | stored_pathname = candidate_pathname; |
1185 | extra_ino_flags |
1304 | entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF | IFS_INO_BOOTSTRAP_EXE; // procnto needs to have these flags stamped on the inode |
1186 | entry_parms->st_mode = S_IFREG | 0700; // procnto requires 0700 permissions |
1305 | entry_parms->st_mode = S_IFREG | 0700; // procnto requires 0700 permissions |
1187 | image_kernel_ino = extra_ino_flags | (inode_count + 1); |
1306 | image_kernel_ino = entry_parms->extra_ino_flags | (inode_count + 1); |
1188 | } |
1307 | } |
1189 | else if (entry_parms->is_compiled_bootscript) // else is it a startup script ? |
1308 | else if (entry_parms->is_compiled_bootscript) // else is it a startup script ? |
1190 | image_bootscript_ino = inode_count + 1; // save boot script inode number for image header |
1309 | image_bootscript_ino = inode_count + 1; // save boot script inode number for image header |
1191 | 1310 | ||
1192 | // do we already know the data for this data blob ? |
1311 | // do we already know the data for this data blob ? |
1193 | if (entry_parms->data != NULL) |
1312 | if (entry_parms->data != NULL) |
1194 | { |
1313 | { |
1195 | entry_parms->mtime = entry_parms->mtime_for_inline_files; |
1314 | entry_parms->mtime = entry_parms->mtime_for_inline_files; |
1196 | fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" blob (len %zd)\n", extra_ino_flags | (inode_count + 1), entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->datalen); |
1315 | fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" blob (len %zd)\n", entry_parms->extra_ino_flags | (inode_count + 1), entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->datalen); |
1197 | } |
1316 | } |
1198 | else if (buildhost_pathname != NULL) // else was a source file pathname supplied ? |
1317 | else if (buildhost_pathname != NULL) // else was a source file pathname supplied ? |
1199 | { |
1318 | { |
1200 | resolved_pathname = read_filecontents (buildhost_pathname, (entry_parms->search[0] != 0 ? entry_parms->search : MKIFS_PATH), &entry_parms->data, &entry_parms->datalen); // locate the file |
1319 | resolved_pathname = read_filecontents (buildhost_pathname, (entry_parms->search[0] != 0 ? entry_parms->search : MKIFS_PATH), &entry_parms->data, &entry_parms->datalen); // locate the file |
1201 | if (resolved_pathname == NULL) |
1320 | if (resolved_pathname == NULL) |
Line 1210... | Line 1329... | ||
1210 | } |
1329 | } |
1211 | 1330 | ||
1212 | // is the file we're storing an ELF file ? |
1331 | // is the file we're storing an ELF file ? |
1213 | if ((entry_parms->datalen > 52) // file is big enough to contain an ELF header |
1332 | if ((entry_parms->datalen > 52) // file is big enough to contain an ELF header |
1214 | && ((elf = (elf_header_t *) entry_parms->data) != NULL) // cast (necessary true) |
1333 | && ((elf = (elf_header_t *) entry_parms->data) != NULL) // cast (necessary true) |
1215 | && (memcmp ( |
1334 | && (memcmp (ELF_GET_STRING (elf, elf, magic), ELF_MAGIC_STR, 4) == 0)) // file starts with the ELF magic |
1216 | { |
1335 | { |
1217 | shdr_shstr = (elf_section_header_t *) &entry_parms->data[ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_table_offset) + (size_t) ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_item_size) * ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_names_idx)]; // quick access to section header for the section that contains the section names |
- | |
1218 | shtable_strings = &entry_parms->data[ELF_STRUCT_MEMBER_NUMERIC (elf, shdr_shstr, file_offset)]; // locate the start of the strings table that contains the section names |
- | |
1219 | - | ||
1220 | // strip this ELF file |
- | |
1221 | - | ||
1222 | // is the file we're storing a relocatable executable (i.e. a dynamic library) and should we check for its canonical name ? |
1336 | // is the file we're storing a relocatable executable (i.e. a dynamic library) and should we check for its canonical name ? |
1223 | if (( |
1337 | if ((ELF_GET_NUMERIC (elf, elf, type) == 3) && entry_parms->should_autosymlink_dylib) |
1224 | { |
1338 | { |
1225 | // we need to find the SONAME of this library |
1339 | // we need to find the SONAME of this library |
1226 | canonical_dylib_name = NULL; |
1340 | canonical_dylib_name = NULL; |
1227 | 1341 | ||
1228 | // locate the sections we need (the dynamic section and its strings table) |
1342 | // locate the sections we need (the dynamic section and its strings table) |
1229 | table_count = ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_table_len); |
- | |
1230 | shdr_dynamic = NULL; |
- | |
1231 | shdr_dynstr = NULL; |
- | |
1232 | for (table_index = 0; table_index < table_count; table_index++) |
- | |
1233 | { |
- | |
1234 |
|
1343 | shdr_dynamic = elf_get_section_header_by_name (elf, ".dynamic"); |
1235 | elf_section_name = &shtable_strings[ELF_STRUCT_MEMBER_NUMERIC (elf, shdr, name_offset)]; |
- | |
1236 | if (strcmp (elf_section_name, ".dynamic") == 0) |
- | |
1237 | shdr_dynamic = shdr; |
- | |
1238 |
|
1344 | shdr_dynstr = elf_get_section_header_by_name (elf, ".dynstr"); |
1239 | shdr_dynstr = shdr; |
- | |
1240 | } |
- | |
1241 | 1345 | ||
1242 | // make sure we have both the dynamic section header and its own strings table header |
1346 | // make sure we have both the dynamic section header and its own strings table header |
1243 | if ((shdr_dynamic != NULL) && (shdr_dynstr != NULL)) |
1347 | if ((shdr_dynamic != NULL) && (shdr_dynstr != NULL)) |
1244 | { |
1348 | { |
1245 | dynamic_strings = (char *) &entry_parms->data[ |
1349 | dynamic_strings = (char *) &entry_parms->data[ELF_GET_NUMERIC (elf, shdr_dynstr, file_offset)]; // quick access to dynamic sections strings table |
1246 | 1350 | ||
1247 | // walk through the dynamic section, look for the DT_SONAME entry |
1351 | // walk through the dynamic section, look for the DT_SONAME entry |
1248 | for (dynamic_entry = (elf_dynamic_section_entry_t *) &entry_parms->data[ |
1352 | for (dynamic_entry = (elf_dynamic_section_entry_t *) &entry_parms->data[ELF_GET_NUMERIC (elf, shdr_dynamic, file_offset)]; |
1249 | ( |
1353 | (ELF_GET_NUMERIC (elf, dynamic_entry, tag) != ELF_DT_NULL); |
1250 | dynamic_entry = (elf_dynamic_section_entry_t *) ((uint8_t *) dynamic_entry + ELF_STRUCT_SIZE (elf, dynamic_entry))) |
1354 | dynamic_entry = (elf_dynamic_section_entry_t *) ((uint8_t *) dynamic_entry + ELF_STRUCT_SIZE (elf, dynamic_entry))) |
1251 | if ( |
1355 | if (ELF_GET_NUMERIC (elf, dynamic_entry, tag) == ELF_DT_SONAME) |
1252 | { |
1356 | { |
1253 | canonical_dylib_name = dynamic_strings + |
1357 | canonical_dylib_name = dynamic_strings + ELF_GET_NUMERIC (elf, dynamic_entry, value.as_integer); |
1254 | break; |
1358 | break; |
1255 | } |
1359 | } |
1256 | 1360 | ||
1257 | // do we have it ? |
1361 | // do we have it ? |
1258 | if ((canonical_dylib_name != NULL) && (canonical_dylib_name[0] != 0)) |
1362 | if ((canonical_dylib_name != NULL) && (canonical_dylib_name[0] != 0)) |
Line 1264... | Line 1368... | ||
1264 | stored_pathname = candidate_pathname; |
1368 | stored_pathname = candidate_pathname; |
1265 | } |
1369 | } |
1266 | } |
1370 | } |
1267 | } |
1371 | } |
1268 | } // end if the file we're storing is a dylib |
1372 | } // end if the file we're storing is a dylib |
- | 1373 | ||
- | 1374 | // now strip this ELF file if necessary |
|
- | 1375 | if (!(entry_parms->extra_ino_flags & IFS_INO_PROCESSED_ELF)) |
|
- | 1376 | { |
|
- | 1377 | // NOTE: for each ELF file, mkifs |
|
- | 1378 | // -> alters the program header table and offsets each p_addr (physical address) member by 0x1400000 plus the current file offset (this cannot be done right now, will need to be done once they are known) |
|
- | 1379 | // -> throws away and reconstructs the sections table by keeping only the sections that are in the program header, and writes the section table at the start of the first thrown-away section |
|
- | 1380 | // FIXME: what if a section thrown away is located between two program segments ? are they collapsed, moving everything one slot down ? this looks improbable... |
|
- | 1381 | ||
- | 1382 | // reconstructed ELF: |
|
- | 1383 | // ==== START OF FILE ==== |
|
- | 1384 | // ELF header |
|
- | 1385 | // program header table |
|
- | 1386 | // (same sections, just p_addr offset down by first section's p_addr) |
|
- | 1387 | // section data 5 (named ".note.gnu.build-id") |
|
- | 1388 | // "............GNU....ZY.....c.o..l" |
|
- | 1389 | // PROGRAM |
|
- | 1390 | // sections table |
|
- | 1391 | // + section 1: ALL ZEROES |
|
- | 1392 | // + section 2: fileoffs 0x21a8 size 0xfd --> "QNX_info" --> QNX binary description: "NAME=pci_debug2.so.3.0\nDESCRIPTION=PCI Server System Debug Module\nDATE=2023/11/19-10:01:13-EST\nSTATE=lookup\nHOST=docker-n1.bts.rim.net\nUSER=builder\nVERSION=QNXOS_main\nTAGID=QNXOS_800-135\nPACKAGE=com.qnx.qnx800.target.pci.debug/3.0.0.00135T202311191043L\n" |
|
- | 1393 | // + section 3: fileoffs 0x22a5 size 0x1c --> ".gnu_debuglink" --> indicates the debug file (and a possible checksum?): "pci_debug2.so.3.0.sym" "\0\0\0" "VX2p" |
|
- | 1394 | // + section 4: fileoffs 0x22c1 size 0x2ad --> "QNX_usage" --> HELP TEXT: "\n-------------------------------------------------------------------------------\n%C\n\nThis module implements debug logging for all PCI server modules. It is\nincluded by setting the environment variable PCI_DEBUG_MODULE and uses\nthe slogger2 APIs.\nNOTE:.On systems which support slogger2, you are encouraged to use this module.instead of pci_debug.so...Release History.---------------..3.0 - This module is functionally equivalent to the previous 2.x version. however it is incompatible with all pre v3.x PCI components..2.1 - fixes a bug whereby if slogger2 is not running and the PCI_DEBUG_MODULE. environment variable is set, the client will SIGSEGV..2.0 - initial release.." |
|
- | 1395 | // + section 5: fileoffs 0x190 size 0x32 --> ".note.gnu.build-id" --> GNU build ID |
|
- | 1396 | // + section 6: fileoffs 0x256e size 0x40 --> ".shstrtab" --> sections names strings table |
|
- | 1397 | // section data 2 (named "QNX_info") |
|
- | 1398 | // (QNX binary description) |
|
- | 1399 | // section data 3 (named ".gnu_debuglink") |
|
- | 1400 | // (debug file) |
|
- | 1401 | // section data 4 (named "QNX_usage") |
|
- | 1402 | // (help text) |
|
- | 1403 | // section data 6 (named ".shstrtab") |
|
- | 1404 | // "\0" |
|
- | 1405 | // ".shstrtab\0" |
|
- | 1406 | // "QNX_info\0" |
|
- | 1407 | // ".gnu_debuglink\0" |
|
- | 1408 | // "QNX_usage\0" |
|
- | 1409 | // ".note.gnu.build-id\0" |
|
- | 1410 | // ==== END OF FILE ==== |
|
- | 1411 | ||
- | 1412 | // task 1: alter the program header table, and measure the farthest offset known by this table where we'll write the reconstructed section headers table |
|
- | 1413 | ||
- | 1414 | //first_offset = SIZE_MAX; |
|
- | 1415 | new_shdrtable_offset = 0; |
|
- | 1416 | table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); |
|
- | 1417 | for (table_index = 0; table_index < table_count; table_index++) |
|
- | 1418 | { |
|
- | 1419 | phdr = (elf_program_header_t *) &entry_parms->data[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header |
|
- | 1420 | //if (first_offset == SIZE_MAX) |
|
- | 1421 | // first_offset = ELF_GET_NUMERIC (elf, phdr, physical_addr); |
|
- | 1422 | if (ELF_GET_NUMERIC (elf, phdr, file_offset) + ELF_GET_NUMERIC (elf, phdr, size_in_file) > new_shdrtable_offset) |
|
- | 1423 | new_shdrtable_offset = ELF_GET_NUMERIC (elf, phdr, file_offset) + ELF_GET_NUMERIC (elf, phdr, size_in_file); |
|
- | 1424 | // ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + (0x1400000 + )); |
|
- | 1425 | } |
|
- | 1426 | ||
- | 1427 | // task 2: re-create the section header table |
|
- | 1428 | ||
- | 1429 | elfsection_shstrtab_data = malloc (1); // initialize an empty section headers strings table |
|
- | 1430 | WELLMANNERED_ASSERT (elfsection_shstrtab_data, "out of memory"); |
|
- | 1431 | elfsection_shstrtab_data[0] = 0; |
|
- | 1432 | elfsection_shstrtab_size = 1; |
|
- | 1433 | ADD_NAME_TO_STRINGTABLE (".shstrtab", &elfsection_shstrtab_data, &elfsection_shstrtab_size); |
|
- | 1434 | ||
- | 1435 | reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
|
- | 1436 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
|
- | 1437 | new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer |
|
- | 1438 | memset (&new_shdr_table[new_shdr_tablesize], 0, ELF_STRUCT_SIZE (elf, shdr)); // the first section header is always zerofilled |
|
- | 1439 | new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
|
- | 1440 | if ((shdr = elf_get_section_header_by_name (elf, "QNX_info")) != NULL) |
|
- | 1441 | { |
|
- | 1442 | if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it |
|
- | 1443 | { |
|
- | 1444 | elfsection_qnxinfo_size = ELF_GET_NUMERIC (elf, shdr, size); |
|
- | 1445 | elfsection_qnxinfo_data = malloc (elfsection_qnxinfo_size); |
|
- | 1446 | WELLMANNERED_ASSERT (elfsection_qnxinfo_data, "out of memory"); |
|
- | 1447 | memcpy (elfsection_qnxinfo_data, &entry_parms->data[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_qnxinfo_size); |
|
- | 1448 | } |
|
- | 1449 | reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
|
- | 1450 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
|
- | 1451 | new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer |
|
- | 1452 | new_qnxinfo_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header |
|
- | 1453 | new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
|
- | 1454 | ||
- | 1455 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_qnxinfo_shdr_offset]; // now populate this section header |
|
- | 1456 | ADD_NAME_TO_STRINGTABLE ("QNX_info", &elfsection_shstrtab_data, &elfsection_shstrtab_size); |
|
- | 1457 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_info", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name |
|
- | 1458 | ELF_SET_NUMERIC (elf, new_shdr, type, ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type |
|
- | 1459 | ELF_SET_NUMERIC (elf, new_shdr, flags, ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags |
|
- | 1460 | ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address |
|
- | 1461 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move |
|
- | 1462 | ELF_SET_NUMERIC (elf, new_shdr, size, ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size |
|
- | 1463 | ELF_SET_NUMERIC (elf, new_shdr, linked_index, ELF_GET_NUMERIC (elf, shdr, linked_index)); // duplicate section linked index (FIXME: may be wrong now!) |
|
- | 1464 | ELF_SET_NUMERIC (elf, new_shdr, info, ELF_GET_NUMERIC (elf, shdr, info)); // duplicate section info |
|
- | 1465 | ELF_SET_NUMERIC (elf, new_shdr, alignment, ELF_GET_NUMERIC (elf, shdr, alignment)); // duplicate section alignment |
|
- | 1466 | ELF_SET_NUMERIC (elf, new_shdr, entry_size, ELF_GET_NUMERIC (elf, shdr, entry_size)); // duplicate section entry size |
|
- | 1467 | } |
|
- | 1468 | if ((shdr = elf_get_section_header_by_name (elf, ".gnu_debuglink")) != NULL) |
|
- | 1469 | { |
|
- | 1470 | if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it |
|
- | 1471 | { |
|
- | 1472 | elfsection_debuglink_size = ELF_GET_NUMERIC (elf, shdr, size); |
|
- | 1473 | elfsection_debuglink_data = malloc (elfsection_debuglink_size); |
|
- | 1474 | WELLMANNERED_ASSERT (elfsection_debuglink_data, "out of memory"); |
|
- | 1475 | memcpy (elfsection_debuglink_data, &entry_parms->data[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_debuglink_size); |
|
- | 1476 | } |
|
- | 1477 | reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
|
- | 1478 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
|
- | 1479 | new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer |
|
- | 1480 | new_debuglink_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header |
|
- | 1481 | new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
|
- | 1482 | ||
- | 1483 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_debuglink_shdr_offset]; // now populate this section header |
|
- | 1484 | ADD_NAME_TO_STRINGTABLE (".gnu_debuglink", &elfsection_shstrtab_data, &elfsection_shstrtab_size); |
|
- | 1485 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".gnu_debuglink", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name |
|
- | 1486 | ELF_SET_NUMERIC (elf, new_shdr, type, ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type |
|
- | 1487 | ELF_SET_NUMERIC (elf, new_shdr, flags, ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags |
|
- | 1488 | ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address |
|
- | 1489 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move |
|
- | 1490 | ELF_SET_NUMERIC (elf, new_shdr, size, ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size |
|
- | 1491 | ELF_SET_NUMERIC (elf, new_shdr, linked_index, ELF_GET_NUMERIC (elf, shdr, linked_index)); // duplicate section linked index (FIXME: may be wrong now!) |
|
- | 1492 | ELF_SET_NUMERIC (elf, new_shdr, info, ELF_GET_NUMERIC (elf, shdr, info)); // duplicate section info |
|
- | 1493 | ELF_SET_NUMERIC (elf, new_shdr, alignment, ELF_GET_NUMERIC (elf, shdr, alignment)); // duplicate section alignment |
|
- | 1494 | ELF_SET_NUMERIC (elf, new_shdr, entry_size, ELF_GET_NUMERIC (elf, shdr, entry_size)); // duplicate section entry size |
|
- | 1495 | } |
|
- | 1496 | if ((shdr = elf_get_section_header_by_name (elf, "QNX_usage")) != NULL) |
|
- | 1497 | { |
|
- | 1498 | if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it |
|
- | 1499 | { |
|
- | 1500 | elfsection_qnxusage_size = ELF_GET_NUMERIC (elf, shdr, size); |
|
- | 1501 | elfsection_qnxusage_data = malloc (elfsection_qnxusage_size); |
|
- | 1502 | WELLMANNERED_ASSERT (elfsection_qnxusage_data, "out of memory"); |
|
- | 1503 | memcpy (elfsection_qnxusage_data, &entry_parms->data[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_qnxusage_size); |
|
- | 1504 | } |
|
- | 1505 | reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
|
- | 1506 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
|
- | 1507 | new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer |
|
- | 1508 | new_qnxusage_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header |
|
- | 1509 | new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
|
- | 1510 | ||
- | 1511 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_qnxusage_shdr_offset]; // now populate this section header |
|
- | 1512 | ADD_NAME_TO_STRINGTABLE ("QNX_usage", &elfsection_shstrtab_data, &elfsection_shstrtab_size); |
|
- | 1513 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_usage", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name |
|
- | 1514 | ELF_SET_NUMERIC (elf, new_shdr, type, ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type |
|
- | 1515 | ELF_SET_NUMERIC (elf, new_shdr, flags, ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags |
|
- | 1516 | ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address |
|
- | 1517 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move |
|
- | 1518 | ELF_SET_NUMERIC (elf, new_shdr, size, ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size |
|
- | 1519 | ELF_SET_NUMERIC (elf, new_shdr, linked_index, ELF_GET_NUMERIC (elf, shdr, linked_index)); // duplicate section linked index (FIXME: may be wrong now!) |
|
- | 1520 | ELF_SET_NUMERIC (elf, new_shdr, info, ELF_GET_NUMERIC (elf, shdr, info)); // duplicate section info |
|
- | 1521 | ELF_SET_NUMERIC (elf, new_shdr, alignment, ELF_GET_NUMERIC (elf, shdr, alignment)); // duplicate section alignment |
|
- | 1522 | ELF_SET_NUMERIC (elf, new_shdr, entry_size, ELF_GET_NUMERIC (elf, shdr, entry_size)); // duplicate section entry size |
|
- | 1523 | } |
|
- | 1524 | if ((shdr = elf_get_section_header_by_name (elf, ".note.gnu.build-id")) != NULL) |
|
- | 1525 | { |
|
- | 1526 | if (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset) // if this section needs to be moved around, have a copy of it |
|
- | 1527 | { |
|
- | 1528 | elfsection_buildid_size = ELF_GET_NUMERIC (elf, shdr, size); |
|
- | 1529 | elfsection_buildid_data = malloc (elfsection_buildid_size); |
|
- | 1530 | WELLMANNERED_ASSERT (elfsection_buildid_data, "out of memory"); |
|
- | 1531 | memcpy (elfsection_buildid_data, &entry_parms->data[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_buildid_size); |
|
- | 1532 | } |
|
- | 1533 | reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
|
- | 1534 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
|
- | 1535 | new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer |
|
- | 1536 | new_buildid_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header |
|
- | 1537 | new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
|
- | 1538 | ||
- | 1539 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_buildid_shdr_offset]; // now populate this section header |
|
- | 1540 | ADD_NAME_TO_STRINGTABLE (".note.gnu.build-id", &elfsection_shstrtab_data, &elfsection_shstrtab_size); |
|
- | 1541 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".note.gnu.build-id", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name |
|
- | 1542 | ELF_SET_NUMERIC (elf, new_shdr, type, ELF_GET_NUMERIC (elf, shdr, type)); // duplicate section type |
|
- | 1543 | ELF_SET_NUMERIC (elf, new_shdr, flags, ELF_GET_NUMERIC (elf, shdr, flags)); // duplicate section flags |
|
- | 1544 | ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, ELF_GET_NUMERIC (elf, shdr, virtual_addr)); // duplicate section virtual address |
|
- | 1545 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, (ELF_GET_NUMERIC (elf, shdr, file_offset) > new_shdrtable_offset ? WILL_BE_FILLED_LATER : ELF_GET_NUMERIC (elf, shdr, file_offset))); // duplicate section offset only if it doesn't move |
|
- | 1546 | ELF_SET_NUMERIC (elf, new_shdr, size, ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size |
|
- | 1547 | ELF_SET_NUMERIC (elf, new_shdr, linked_index, ELF_GET_NUMERIC (elf, shdr, linked_index)); // duplicate section linked index (FIXME: may be wrong now!) |
|
- | 1548 | ELF_SET_NUMERIC (elf, new_shdr, info, ELF_GET_NUMERIC (elf, shdr, info)); // duplicate section info |
|
- | 1549 | ELF_SET_NUMERIC (elf, new_shdr, alignment, ELF_GET_NUMERIC (elf, shdr, alignment)); // duplicate section alignment |
|
- | 1550 | ELF_SET_NUMERIC (elf, new_shdr, entry_size, ELF_GET_NUMERIC (elf, shdr, entry_size)); // duplicate section entry size |
|
- | 1551 | } |
|
- | 1552 | reallocated_ptr = realloc (new_shdr_table, new_shdr_tablesize + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
|
- | 1553 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
|
- | 1554 | new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer |
|
- | 1555 | new_shstrtab_shdr_offset = new_shdr_tablesize; // remember the new offset of this section header |
|
- | 1556 | new_shdr_tablesize += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
|
- | 1557 | ||
- | 1558 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_shstrtab_shdr_offset]; // now populate this section header |
|
- | 1559 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".shstrtab", elfsection_shstrtab_data, elfsection_shstrtab_size)); // update the relative offset of the section name |
|
- | 1560 | ELF_SET_NUMERIC (elf, new_shdr, type, ELF_SECTIONTYPE_STRINGTABLE); // section type (SHT_STRTAB) |
|
- | 1561 | ELF_SET_NUMERIC (elf, new_shdr, flags, 0); // section flags (we could set SHF_STRINGS i.e. 0x20 here, but mkifs does not, so mimic that) |
|
- | 1562 | ELF_SET_NUMERIC (elf, new_shdr, virtual_addr, 0); // this section does not need to be mapped |
|
- | 1563 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, WILL_BE_FILLED_LATER); // FIXME |
|
- | 1564 | ELF_SET_NUMERIC (elf, new_shdr, size, elfsection_shstrtab_size); // section size |
|
- | 1565 | ELF_SET_NUMERIC (elf, new_shdr, linked_index, 0); // this section is not linked to any other |
|
- | 1566 | ELF_SET_NUMERIC (elf, new_shdr, info, 0); // this section has no additional info |
|
- | 1567 | ELF_SET_NUMERIC (elf, new_shdr, alignment, 1); // this section is byte-aligned |
|
- | 1568 | ELF_SET_NUMERIC (elf, new_shdr, entry_size, 0); // this section is not a table, so entry_size is zero |
|
- | 1569 | ||
- | 1570 | // jump over the new section headers table and write the sections that need to be relocated after the section headers table |
|
- | 1571 | entry_parms->datalen = new_shdrtable_offset + new_shdr_tablesize; // assume there are no sections beyond the section headers table until known otherwise |
|
- | 1572 | if (elfsection_qnxinfo_data != NULL) |
|
- | 1573 | { |
|
- | 1574 | memcpy (&entry_parms->data[entry_parms->datalen], elfsection_qnxinfo_data, elfsection_qnxinfo_size); // write section in place |
|
- | 1575 | free (elfsection_qnxinfo_data); // free it |
|
- | 1576 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_qnxinfo_shdr_offset]; // now fix this section header |
|
- | 1577 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table |
|
- | 1578 | entry_parms->datalen += elfsection_qnxinfo_size; // update new ELF file length |
|
- | 1579 | } |
|
- | 1580 | if (elfsection_debuglink_data != NULL) |
|
- | 1581 | { |
|
- | 1582 | memcpy (&entry_parms->data[entry_parms->datalen], elfsection_debuglink_data, elfsection_debuglink_size); // write section in place |
|
- | 1583 | free (elfsection_debuglink_data); // free it |
|
- | 1584 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_debuglink_shdr_offset]; // now fix this section header |
|
- | 1585 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table |
|
- | 1586 | entry_parms->datalen += elfsection_debuglink_size; // update new ELF file length |
|
- | 1587 | } |
|
- | 1588 | if (elfsection_qnxusage_data != NULL) |
|
- | 1589 | { |
|
- | 1590 | memcpy (&entry_parms->data[entry_parms->datalen], elfsection_qnxusage_data, elfsection_qnxusage_size); // write section in place |
|
- | 1591 | free (elfsection_qnxusage_data); // free it |
|
- | 1592 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_qnxusage_shdr_offset]; // now fix this section header |
|
- | 1593 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table |
|
- | 1594 | entry_parms->datalen += elfsection_qnxusage_size; // update new ELF file length |
|
- | 1595 | } |
|
- | 1596 | if (elfsection_buildid_data != NULL) |
|
- | 1597 | { |
|
- | 1598 | memcpy (&entry_parms->data[entry_parms->datalen], elfsection_buildid_data, elfsection_buildid_size); // write section in place |
|
- | 1599 | free (elfsection_buildid_data); // free it |
|
- | 1600 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_buildid_shdr_offset]; // now fix this section header |
|
- | 1601 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table |
|
- | 1602 | entry_parms->datalen += elfsection_buildid_size; // update new ELF file length |
|
- | 1603 | } |
|
- | 1604 | if (elfsection_shstrtab_data != NULL) |
|
- | 1605 | { |
|
- | 1606 | memcpy (&entry_parms->data[entry_parms->datalen], elfsection_shstrtab_data, elfsection_shstrtab_size); // write section header strings table section in place |
|
- | 1607 | free (elfsection_shstrtab_data); |
|
- | 1608 | new_shdr = (elf_section_header_t *) &new_shdr_table[new_shstrtab_shdr_offset]; // now fix this section header |
|
- | 1609 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->datalen); // fix section offset in the new section headers table |
|
- | 1610 | entry_parms->datalen += elfsection_shstrtab_size; // update new ELF file length |
|
- | 1611 | } |
|
- | 1612 | ||
- | 1613 | // now write the section headers table |
|
- | 1614 | fprintf (stderr, "rewriting section headers table at offset 0x%zd\n", new_shdrtable_offset); |
|
- | 1615 | memcpy (&entry_parms->data[new_shdrtable_offset], new_shdr_table, new_shdr_tablesize); |
|
- | 1616 | free (new_shdr_table); // free it |
|
- | 1617 | ||
- | 1618 | // and finally fix the ELF header |
|
- | 1619 | ELF_SET_NUMERIC (elf, elf, section_header_table_offset, new_shdrtable_offset); |
|
- | 1620 | ELF_SET_NUMERIC (elf, elf, section_header_table_len, new_shdr_tablesize / ELF_STRUCT_SIZE (elf, shdr)); |
|
- | 1621 | ELF_SET_NUMERIC (elf, elf, section_header_names_idx, new_shdr_tablesize / ELF_STRUCT_SIZE (elf, shdr) - 1); // the section headers strings table is the last section |
|
- | 1622 | ||
- | 1623 | // align size with page size (4096 on x86, 16k on ARM) |
|
- | 1624 | end_padding_offset = entry_parms->datalen; |
|
- | 1625 | if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_X86_64) |
|
- | 1626 | entry_parms->datalen = ROUND_TO_UPPER_MULTIPLE (end_padding_offset, 4 * 1024); // 4 kb pages on Intel processors |
|
- | 1627 | else if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_AARCH64) |
|
- | 1628 | entry_parms->datalen = ROUND_TO_UPPER_MULTIPLE (end_padding_offset, 16 * 1024); // 16 kb pages on ARM64 |
|
- | 1629 | else |
|
- | 1630 | { |
|
- | 1631 | fprintf (stderr, "fatal error: this ELF file \"%s\" does not belong to an architecture supported by ifstool (neither x86_64, nor aarch64)\n", stored_pathname); |
|
- | 1632 | exit (1); |
|
- | 1633 | } |
|
- | 1634 | memset (&entry_parms->data[end_padding_offset], 0, entry_parms->datalen - end_padding_offset); // zerofill |
|
- | 1635 | ||
- | 1636 | entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF; // mark this inode as a preprocessed ELF file |
|
- | 1637 | } // end if the file is not yet a processed ELF |
|
1269 | } // end if the file we're storing is an ELF file |
1638 | } // end if the file we're storing is an ELF file |
1270 | } |
1639 | } |
1271 | else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ? |
1640 | else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ? |
1272 | fprintf (stderr, "symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data); |
1641 | fprintf (stderr, "symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data); |
1273 | else // we must be storing a FIFO |
1642 | else // we must be storing a FIFO |
Line 1289... | Line 1658... | ||
1289 | } |
1658 | } |
1290 | *fsentries = reallocated_ptr; // save reallocated pointer |
1659 | *fsentries = reallocated_ptr; // save reallocated pointer |
1291 | fsentry = &(*fsentries)[*fsentry_count]; // quick access to fs entry slot |
1660 | fsentry = &(*fsentries)[*fsentry_count]; // quick access to fs entry slot |
1292 | //fsentry->header.size = 0; // will be filled once we know it |
1661 | //fsentry->header.size = 0; // will be filled once we know it |
1293 | fsentry->header.extattr_offset = 0; |
1662 | fsentry->header.extattr_offset = 0; |
1294 | fsentry->header.ino = extra_ino_flags | (++inode_count); |
1663 | fsentry->header.ino = entry_parms->extra_ino_flags | (++inode_count); |
1295 | fsentry->header.mode = entry_parms->st_mode; |
1664 | fsentry->header.mode = entry_parms->st_mode; |
1296 | fsentry->header.gid = entry_parms->gid; |
1665 | fsentry->header.gid = entry_parms->gid; |
1297 | fsentry->header.uid = entry_parms->uid; |
1666 | fsentry->header.uid = entry_parms->uid; |
1298 | fsentry->header.mtime = (entry_parms->mtime == UINT32_MAX ? (uint32_t) time (NULL) : entry_parms->mtime); |
1667 | fsentry->header.mtime = (entry_parms->mtime == UINT32_MAX ? (uint32_t) time (NULL) : entry_parms->mtime); |
1299 | if (S_ISDIR (entry_parms->st_mode)) |
1668 | if (S_ISDIR (entry_parms->st_mode)) |
Line 1338... | Line 1707... | ||
1338 | { |
1707 | { |
1339 | entry_parms->is_compiled_bootscript = false; |
1708 | entry_parms->is_compiled_bootscript = false; |
1340 | entry_parms->should_autosymlink_dylib = false; |
1709 | entry_parms->should_autosymlink_dylib = false; |
1341 | entry_parms->should_follow_symlinks = false; |
1710 | entry_parms->should_follow_symlinks = false; |
1342 | entry_parms->st_mode = S_IFLNK | 0777; // NOTE: mkifs stores symlink permissions as rwxrwxrwx ! |
1711 | entry_parms->st_mode = S_IFLNK | 0777; // NOTE: mkifs stores symlink permissions as rwxrwxrwx ! |
- | 1712 | entry_parms->extra_ino_flags = (fsentry->header.ino & (IFS_INO_PROCESSED_ELF | IFS_INO_RUNONCE_ELF | IFS_INO_BOOTSTRAP_EXE)); // preserve target's inode flags |
|
1343 | last_dirsep = strrchr (stored_pathname, '/'); |
1713 | last_dirsep = strrchr (stored_pathname, '/'); |
1344 | old_data = entry_parms->data; // backup previous data pointer |
1714 | old_data = entry_parms->data; // backup previous data pointer |
1345 | entry_parms->data = (uint8_t *) (last_dirsep == NULL ? stored_pathname : last_dirsep + 1); // store symlink target in dirent data |
1715 | entry_parms->data = (uint8_t *) (last_dirsep == NULL ? stored_pathname : last_dirsep + 1); // store symlink target in dirent data |
1346 | entry_parms->datalen = strlen (entry_parms->data); |
1716 | entry_parms->datalen = strlen (entry_parms->data); |
1347 | add_fsentry (fsentries, fsentry_count, entry_parms, original_stored_pathname, NULL); |
1717 | add_fsentry (fsentries, fsentry_count, entry_parms, original_stored_pathname, NULL); |
Line 1429... | Line 1799... | ||
1429 | .mtime_for_inline_files = UINT32_MAX, |
1799 | .mtime_for_inline_files = UINT32_MAX, |
1430 | .prefix = "/proc/boot", |
1800 | .prefix = "/proc/boot", |
1431 | .should_follow_symlinks = true, // [+|-followlink] |
1801 | .should_follow_symlinks = true, // [+|-followlink] |
1432 | .should_autosymlink_dylib = true, // [+|-autolink] |
1802 | .should_autosymlink_dylib = true, // [+|-autolink] |
1433 | .is_compiled_bootscript = false, // [+|-script] |
1803 | .is_compiled_bootscript = false, // [+|-script] |
- | 1804 | .extra_ino_flags = 0, |
|
1434 | .search = "", |
1805 | .search = "", |
1435 | .data = NULL, |
1806 | .data = NULL, |
1436 | .datalen = 0 |
1807 | .datalen = 0 |
1437 | }; |
1808 | }; |
1438 | static parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file) |
1809 | static parms_t entry_parms = { 0 }; // current parameters for a filesystem entry (will be initialized to default_parms each time a new entry is parsed in the build file) |
Line 1447... | Line 1818... | ||
1447 | 1818 | ||
1448 | char path_on_buildhost[MAXPATHLEN] = ""; |
1819 | char path_on_buildhost[MAXPATHLEN] = ""; |
1449 | char path_in_ifs[MAXPATHLEN] = ""; |
1820 | char path_in_ifs[MAXPATHLEN] = ""; |
1450 | char *ifs_pathname = NULL; |
1821 | char *ifs_pathname = NULL; |
1451 | void *reallocated_ptr; |
1822 | void *reallocated_ptr; |
- | 1823 | const elf_header_t *elf; |
|
- | 1824 | elf_program_header_t *phdr; |
|
1452 | struct tm utc_time; |
1825 | struct tm utc_time; |
1453 | struct stat stat_buf; |
1826 | struct stat stat_buf; |
1454 | size_t startuptrailer_offset; |
1827 | size_t startuptrailer_offset; |
1455 | size_t startupheader_offset; |
1828 | size_t startupheader_offset; |
1456 | size_t imagetrailer_offset; |
1829 | size_t imagetrailer_offset; |
Line 1463... | Line 1836... | ||
1463 | size_t allocated_size; |
1836 | size_t allocated_size; |
1464 | size_t fsentry_index; |
1837 | size_t fsentry_index; |
1465 | size_t largest_index; |
1838 | size_t largest_index; |
1466 | size_t largest_size; |
1839 | size_t largest_size; |
1467 | size_t curr_offset; |
1840 | size_t curr_offset; |
- | 1841 | size_t table_index; |
|
- | 1842 | size_t table_count; |
|
1468 | uint8_t *blob_data; |
1843 | uint8_t *blob_data; |
1469 | int32_t checksum; |
1844 | int32_t checksum; |
1470 | char *specifiedpathname_start; |
1845 | char *specifiedpathname_start; |
1471 | char *directiveblock_start; |
1846 | char *directiveblock_start; |
1472 | char *write_ptr; |
1847 | char *write_ptr; |
Line 1478... | Line 1853... | ||
1478 | int arg_index; |
1853 | int arg_index; |
1479 | bool is_quoted_context = false; |
1854 | bool is_quoted_context = false; |
1480 | bool is_escaped_char = false; |
1855 | bool is_escaped_char = false; |
1481 | bool has_data_already = false; |
1856 | bool has_data_already = false; |
1482 | bool want_info = false; |
1857 | bool want_info = false; |
- | 1858 | bool want_everything = false; |
|
1483 | bool want_help = false; |
1859 | bool want_help = false; |
1484 | bool is_foreign_endianness; |
1860 | bool is_foreign_endianness; |
1485 | int string_len; |
1861 | int string_len; |
1486 | int read_char; |
1862 | int read_char; |
1487 | FILE *buildfile_fp; |
1863 | FILE *buildfile_fp; |
Line 1523... | Line 1899... | ||
1523 | default_parms.mtime = 0; // all files should have a mtime set to zero |
1899 | default_parms.mtime = 0; // all files should have a mtime set to zero |
1524 | default_parms.mtime_for_inline_files = 0; |
1900 | default_parms.mtime_for_inline_files = 0; |
1525 | } |
1901 | } |
1526 | else if (strcmp (argv[arg_index], "--info") == 0) |
1902 | else if (strcmp (argv[arg_index], "--info") == 0) |
1527 | want_info = true; |
1903 | want_info = true; |
- | 1904 | else if (strcmp (argv[arg_index], "--everything") == 0) |
|
- | 1905 | want_everything = true; |
|
1528 | else if ((strcmp (argv[arg_index], "-?") == 0) || (strcmp (argv[arg_index], "--help") == 0)) |
1906 | else if ((strcmp (argv[arg_index], "-?") == 0) || (strcmp (argv[arg_index], "--help") == 0)) |
1529 | want_help = true; |
1907 | want_help = true; |
1530 | else if (buildfile_pathname == NULL) |
1908 | else if (buildfile_pathname == NULL) |
1531 | buildfile_pathname = argv[arg_index]; |
1909 | buildfile_pathname = argv[arg_index]; |
1532 | else if (ifs_pathname == NULL) |
1910 | else if (ifs_pathname == NULL) |
Line 1540... | Line 1918... | ||
1540 | fprintf ((want_help ? stdout : stderr), " version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD); |
1918 | fprintf ((want_help ? stdout : stderr), " version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD); |
1541 | if (!want_help) |
1919 | if (!want_help) |
1542 | fprintf (stderr, "error: missing parameters\n"); |
1920 | fprintf (stderr, "error: missing parameters\n"); |
1543 | fprintf ((want_help ? stdout : stderr), "usage:\n"); |
1921 | fprintf ((want_help ? stdout : stderr), "usage:\n"); |
1544 | fprintf ((want_help ? stdout : stderr), " ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kernelfile <pathname>@<fileoffs>] [-n[n]] <buildfile> <outfile>\n"); |
1922 | fprintf ((want_help ? stdout : stderr), " ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kernelfile <pathname>@<fileoffs>] [-n[n]] <buildfile> <outfile>\n"); |
1545 | fprintf ((want_help ? stdout : stderr), " ifstool --info <ifs file>\n"); |
1923 | fprintf ((want_help ? stdout : stderr), " ifstool --info [--everything] <ifs file>\n"); |
1546 | fprintf ((want_help ? stdout : stderr), " ifstool --help\n"); |
1924 | fprintf ((want_help ? stdout : stderr), " ifstool --help\n"); |
1547 | fprintf ((want_help ? stdout : stderr), "WARNING: the compilation feature is currently a work in progress (broken). Only the --info mode is usable at the moment.\n"); |
1925 | fprintf ((want_help ? stdout : stderr), "WARNING: the compilation feature is currently a work in progress (broken). Only the --info mode is usable at the moment.\n"); |
1548 | exit (want_help ? 0 : 1); |
1926 | exit (want_help ? 0 : 1); |
1549 | } |
1927 | } |
1550 | 1928 | ||
1551 | // do we want info about a particular IFS ? if so, dump it |
1929 | // do we want info about a particular IFS ? if so, dump it |
1552 | if (want_info) |
1930 | if (want_info) |
1553 | exit (dump_ifs_info (buildfile_pathname)); // NOTE: the first argument after --info is actually the IFS file, not a build file, but the arguments are collected in this order |
1931 | exit (dump_ifs_info (buildfile_pathname, want_everything)); // NOTE: the first argument after --info is actually the IFS file, not a build file, but the arguments are collected in this order |
1554 | 1932 | ||
1555 | // make sure we have ${QNX_TARGET} pointing somewhere |
1933 | // make sure we have ${QNX_TARGET} pointing somewhere |
1556 | QNX_TARGET = getenv ("QNX_TARGET"); |
1934 | QNX_TARGET = getenv ("QNX_TARGET"); |
1557 | if (QNX_TARGET == NULL) |
1935 | if (QNX_TARGET == NULL) |
1558 | { |
1936 | { |
Line 1911... | Line 2289... | ||
1911 | memcpy (startup_header.signature, "\xeb\x7e\xff\x00", 4); // startup header signature, i.e. 0xff7eeb |
2289 | memcpy (startup_header.signature, "\xeb\x7e\xff\x00", 4); // startup header signature, i.e. 0xff7eeb |
1912 | startup_header.version = 1; |
2290 | startup_header.version = 1; |
1913 | startup_header.flags1 = STARTUP_HDR_FLAGS1_VIRTUAL | STARTUP_HDR_FLAGS1_TRAILER_V2; // flags, 0x21 (STARTUP_HDR_FLAGS1_VIRTUAL | STARTUP_HDR_FLAGS1_TRAILER_V2) |
2291 | startup_header.flags1 = STARTUP_HDR_FLAGS1_VIRTUAL | STARTUP_HDR_FLAGS1_TRAILER_V2; // flags, 0x21 (STARTUP_HDR_FLAGS1_VIRTUAL | STARTUP_HDR_FLAGS1_TRAILER_V2) |
1914 | startup_header.header_size = sizeof (startup_header); // 256 |
2292 | startup_header.header_size = sizeof (startup_header); // 256 |
1915 | if (strcmp (image_processor, "x86_64") == 0) |
2293 | if (strcmp (image_processor, "x86_64") == 0) |
1916 | startup_header.machine = |
2294 | startup_header.machine = ELF_MACHINE_X86_64; // EM_X86_64 |
1917 | else if (strcmp (image_processor, "aarch64le") == 0) |
2295 | else if (strcmp (image_processor, "aarch64le") == 0) |
1918 | startup_header.machine = |
2296 | startup_header.machine = ELF_MACHINE_AARCH64; // EM_AARCH64 |
1919 | else |
2297 | else |
1920 | { |
2298 | { |
1921 | fprintf (stderr, "fatal error: unsupported processor type '%s' found in build file \"%s\"\n", image_processor, buildfile_pathname); |
2299 | fprintf (stderr, "fatal error: unsupported processor type '%s' found in build file \"%s\"\n", image_processor, buildfile_pathname); |
1922 | exit (1); |
2300 | exit (1); |
1923 | } |
2301 | } |
Line 2005... | Line 2383... | ||
2005 | largest_index = fsentry_index; |
2383 | largest_index = fsentry_index; |
2006 | } |
2384 | } |
2007 | } |
2385 | } |
2008 | if (largest_size == 0) |
2386 | if (largest_size == 0) |
2009 | break; // found none ? if so, stop searching |
2387 | break; // found none ? if so, stop searching |
- | 2388 | ||
- | 2389 | // is the file we're storing a preprocessed ELF file ? |
|
- | 2390 | if (fsentries[fsentry_index].header.ino & IFS_INO_PROCESSED_ELF) |
|
- | 2391 | { |
|
- | 2392 | elf = (elf_header_t *) fsentries[fsentry_index].u.file.UNSAVED_databuf; // quick access to ELF header |
|
- | 2393 | table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); // get the number of program headers |
|
- | 2394 | for (table_index = 0; table_index < table_count; table_index++) |
|
- | 2395 | { |
|
- | 2396 | phdr = (elf_program_header_t *) &fsentries[fsentry_index].u.file.UNSAVED_databuf[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header |
|
- | 2397 | ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + (0x1400000 + curr_offset)); // patch the physical address member of the program header table |
|
- | 2398 | } |
|
- | 2399 | } |
|
2010 | 2400 | ||
2011 | fsentries[largest_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure |
2401 | fsentries[largest_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure |
2012 | fwrite_or_die (fsentries[largest_index].u.file.UNSAVED_databuf, 1, fsentries[largest_index].u.file.size, fp); // write file data blob |
2402 | fwrite_or_die (fsentries[largest_index].u.file.UNSAVED_databuf, 1, fsentries[largest_index].u.file.size, fp); // write file data blob |
2013 | fsentries[largest_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
2403 | fsentries[largest_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
2014 | } |
2404 | } |
- | 2405 | fprintf (stderr, "Current offset: 0x%zx\n", curr_offset); |
|
- | 2406 | fprintf (stderr, "Kernel file offset: 0x%zx\n", kernelfile_offset); |
|
2015 | PAD_OUTFILE_TO (kernelfile_offset); // reach the kernel offset |
2407 | PAD_OUTFILE_TO (kernelfile_offset); // reach the kernel offset |
2016 | 2408 | ||
2017 | // now write the QNX kernel |
2409 | // now write the QNX kernel |
2018 | for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++) |
2410 | for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++) |
2019 | if (fsentries[fsentry_index].header.ino == image_kernel_ino) |
2411 | if (fsentries[fsentry_index].header.ino == image_kernel_ino) |
Line 2035... | Line 2427... | ||
2035 | if (!S_ISREG (fsentries[fsentry_index].header.mode) || fsentries[fsentry_index].UNSAVED_was_data_written // filter out anything that's not a file, and anything that's been already written |
2427 | if (!S_ISREG (fsentries[fsentry_index].header.mode) || fsentries[fsentry_index].UNSAVED_was_data_written // filter out anything that's not a file, and anything that's been already written |
2036 | || (fsentries[fsentry_index].u.file.size < 4) || (memcmp (fsentries[fsentry_index].u.file.UNSAVED_databuf, ELF_MAGIC_STR, 4) != 0)) // filter out anything that's not an ELF file |
2428 | || (fsentries[fsentry_index].u.file.size < 4) || (memcmp (fsentries[fsentry_index].u.file.UNSAVED_databuf, ELF_MAGIC_STR, 4) != 0)) // filter out anything that's not an ELF file |
2037 | continue; // skip all entries that don't have a separate data block and those who were written already |
2429 | continue; // skip all entries that don't have a separate data block and those who were written already |
2038 | curr_offset = ftell (fp); |
2430 | curr_offset = ftell (fp); |
2039 | fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure |
2431 | fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure |
- | 2432 | ||
- | 2433 | // is the file we're storing a preprocessed ELF file ? |
|
- | 2434 | if (fsentries[fsentry_index].header.ino & IFS_INO_PROCESSED_ELF) |
|
- | 2435 | { |
|
- | 2436 | elf = (elf_header_t *) fsentries[fsentry_index].u.file.UNSAVED_databuf; // quick access to ELF header |
|
- | 2437 | table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); // get the number of program headers |
|
- | 2438 | for (table_index = 0; table_index < table_count; table_index++) |
|
- | 2439 | { |
|
- | 2440 | phdr = (elf_program_header_t *) &fsentries[fsentry_index].u.file.UNSAVED_databuf[ELF_GET_NUMERIC (elf, elf, program_header_table_offset) + (size_t) ELF_GET_NUMERIC (elf, elf, program_header_item_size) * table_index]; // quick access to program header |
|
- | 2441 | ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + (0x1400000 + curr_offset)); // patch the physical address member of the program header table |
|
- | 2442 | } |
|
- | 2443 | } |
|
- | 2444 | ||
2040 | fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob |
2445 | fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob |
2041 | fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
2446 | fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
2042 | } |
2447 | } |
2043 | for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++) // other files (non-ELF, e.g. scripts and data files) last |
2448 | for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++) // other files (non-ELF, e.g. scripts and data files) last |
2044 | { |
2449 | { |
Line 2137... | Line 2542... | ||
2137 | fprintf (stdout, "Success\n"); |
2542 | fprintf (stdout, "Success\n"); |
2138 | exit (0); |
2543 | exit (0); |
2139 | } |
2544 | } |
2140 | 2545 | ||
2141 | 2546 | ||
2142 | static int dump_ifs_info (const char *ifs_pathname) |
2547 | static int dump_ifs_info (const char *ifs_pathname, bool want_everything) |
2143 | { |
2548 | { |
2144 | #define hex_printf(buf,size,...) do { \ |
2549 | #define hex_printf(buf,size,...) do { \ |
2145 | if ((size) <= 16 * 1024) /* only print when it's not too big (up to 16 kb) */\ |
2550 | if (want_everything || ((size) <= 16 * 1024)) /* only print when it's not too big (up to 16 kb) */\ |
2146 | hex_fprintf (stdout, (buf), (size), 16, __VA_ARGS__); /* use 16 columns in hex output to stdout */ \ |
2551 | hex_fprintf (stdout, (buf), (size), 16, __VA_ARGS__); /* use 16 columns in hex output to stdout */ \ |
2147 | else { \ |
2552 | else { \ |
2148 | printf (__VA_ARGS__); \ |
2553 | printf (__VA_ARGS__); \ |
2149 | |
2554 | hex_fprintf (stdout, (buf), 1024, 16, " first kilobyte:\n"); \ |
2150 | } \ |
2555 | } \ |
2151 | } while (0) |
2556 | } while (0) |
2152 | #define BINARY(x) binary ((x), '-', 'x') |
2557 | #define BINARY(x) binary ((x), '-', 'x') |
2153 | 2558 | ||
2154 | static const char *startupheader_flags1_strings[8] = { |
2559 | static const char *startupheader_flags1_strings[8] = { |
Line 2232... | Line 2637... | ||
2232 | printf (" signature = %02x %02x %02x %02x - good\n", startup_header->signature[0], startup_header->signature[1], startup_header->signature[2], startup_header->signature[3]); |
2637 | printf (" signature = %02x %02x %02x %02x - good\n", startup_header->signature[0], startup_header->signature[1], startup_header->signature[2], startup_header->signature[3]); |
2233 | printf (" version = 0x%04x (%d) - %s\n", startup_header->version, startup_header->version, (startup_header->version == 1 ? "looks good" : "???")); |
2638 | printf (" version = 0x%04x (%d) - %s\n", startup_header->version, startup_header->version, (startup_header->version == 1 ? "looks good" : "???")); |
2234 | printf (" flags1 = 0x%02x (%s)\n", startup_header->flags1, describe_uint8 (startup_header->flags1, startupheader_flags1_strings)); |
2639 | printf (" flags1 = 0x%02x (%s)\n", startup_header->flags1, describe_uint8 (startup_header->flags1, startupheader_flags1_strings)); |
2235 | printf (" flags2 = 0x%02x (%s) - %s\n", startup_header->flags2, BINARY (startup_header->flags2), (startup_header->flags2 == 0 ? "looks good" : "???")); |
2640 | printf (" flags2 = 0x%02x (%s) - %s\n", startup_header->flags2, BINARY (startup_header->flags2), (startup_header->flags2 == 0 ? "looks good" : "???")); |
2236 | printf (" header_size = 0x%04x (%d) - %s\n", startup_header->header_size, startup_header->header_size, (startup_header->header_size == sizeof (startup_header_t) ? "looks good" : "BAD")); |
2641 | printf (" header_size = 0x%04x (%d) - %s\n", startup_header->header_size, startup_header->header_size, (startup_header->header_size == sizeof (startup_header_t) ? "looks good" : "BAD")); |
2237 | printf (" machine = 0x%04x (%d) - %s\n", startup_header->machine, startup_header->machine, (startup_header->machine == |
2642 | printf (" machine = 0x%04x (%d) - %s\n", startup_header->machine, startup_header->machine, (startup_header->machine == ELF_MACHINE_X86_64 ? "x86_64" : (startup_header->machine == ELF_MACHINE_AARCH64 ? "aarch64" : "unknown"))); |
2238 | printf (" startup_vaddr = 0x%08x (%d) - virtual address to transfer to after IPL is done\n", startup_header->startup_vaddr, startup_header->startup_vaddr); |
2643 | printf (" startup_vaddr = 0x%08x (%d) - virtual address to transfer to after IPL is done\n", startup_header->startup_vaddr, startup_header->startup_vaddr); |
2239 | printf (" paddr_bias = 0x%08x (%d) - value to add to physical addresses to get an indirectable pointer value\n", startup_header->paddr_bias, startup_header->paddr_bias); |
2644 | printf (" paddr_bias = 0x%08x (%d) - value to add to physical addresses to get an indirectable pointer value\n", startup_header->paddr_bias, startup_header->paddr_bias); |
2240 | printf (" image_paddr = 0x%08x (%d) - physical address of image\n", startup_header->image_paddr, startup_header->image_paddr); |
2645 | printf (" image_paddr = 0x%08x (%d) - physical address of image\n", startup_header->image_paddr, startup_header->image_paddr); |
2241 | printf (" ram_paddr = 0x%08x (%d) - physical address of RAM to copy image to (startup_size bytes copied)\n", startup_header->ram_paddr, startup_header->ram_paddr); |
2646 | printf (" ram_paddr = 0x%08x (%d) - physical address of RAM to copy image to (startup_size bytes copied)\n", startup_header->ram_paddr, startup_header->ram_paddr); |
2242 | printf (" ram_size = 0x%08x (%d) - amount of RAM used by the startup program and executables in the fs\n", startup_header->ram_size, startup_header->ram_size); |
2647 | printf (" ram_size = 0x%08x (%d) - amount of RAM used by the startup program and executables in the fs\n", startup_header->ram_size, startup_header->ram_size); |
Line 2467... | Line 2872... | ||
2467 | printf (" corresponding dirent index: %zd/%zd\n", fsentry_index, fsentry_count); |
2872 | printf (" corresponding dirent index: %zd/%zd\n", fsentry_index, fsentry_count); |
2468 | printf (" corresponding inode 0x%08x (%d) -%s%s%s%s\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "" : " nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : "")); |
2873 | printf (" corresponding inode 0x%08x (%d) -%s%s%s%s\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "" : " nothing special"), (current_fsentry->header.ino & IFS_INO_PROCESSED_ELF ? " PROCESSED_ELF" : ""), (current_fsentry->header.ino & IFS_INO_RUNONCE_ELF ? " RUNONCE_ELF" : ""), (current_fsentry->header.ino & IFS_INO_BOOTSTRAP_EXE ? " BOOTSTRAP_EXE" : "")); |
2469 | printf (" corresponding path: \"%s\"\n", (char *) ¤t_fsentry->u.file.path); // convert from pointer to char array |
2874 | printf (" corresponding path: \"%s\"\n", (char *) ¤t_fsentry->u.file.path); // convert from pointer to char array |
2470 | printf (" size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size); |
2875 | printf (" size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size); |
2471 | if (current_offset + 4 < filesize) |
2876 | if (current_offset + 4 < filesize) |
2472 | { |
- | |
2473 | if ((current_fsentry->u.file.size < 16 * 1024) && (current_offset + current_fsentry->u.file.size < filesize)) |
- | |
2474 |
|
2877 | hex_printf (&filedata[current_offset], current_fsentry->u.file.size, " data:\n"); |
2475 | else |
- | |
2476 | printf (" first 4 bytes: %02x%02x%02x%02x \"%c%c%c%c\" (%s)\n", (uint8_t) filedata[current_offset + 0], (uint8_t) filedata[current_offset + 1], (uint8_t) filedata[current_offset + 2], (uint8_t) filedata[current_offset + 3], (isprint (filedata[current_offset + 0]) ? filedata[current_offset + 0] : '.'), (isprint (filedata[current_offset + 1]) ? filedata[current_offset + 1] : '.'), (isprint (filedata[current_offset + 2]) ? filedata[current_offset + 2] : '.'), (isprint (filedata[current_offset + 3]) ? filedata[current_offset + 3] : '.'), (memcmp (&filedata[current_offset], ELF_MAGIC_STR, 4) == 0 ? "ELF binary" : (memcmp (&filedata[current_offset], "#!", 2) == 0 ? "shell script" : "data file"))); |
- | |
2477 | } |
- | |
2478 | if (current_offset + current_fsentry->u.file.size < filesize) |
2878 | if (current_offset + current_fsentry->u.file.size < filesize) |
2479 | printf (" checksum %d\n", update_checksum (&filedata[current_offset], current_fsentry->u.file.size, is_foreign_endianness)); |
2879 | printf (" checksum %d\n", update_checksum (&filedata[current_offset], current_fsentry->u.file.size, is_foreign_endianness)); |
2480 | else |
2880 | else |
2481 | { |
2881 | { |
2482 | printf ("WARNING: this IFS file is corrupted (the size of this file data extends past the IFS size)\n"); |
2882 | printf ("WARNING: this IFS file is corrupted (the size of this file data extends past the IFS size)\n"); |