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");  |