Rev 10 | Rev 12 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
| Rev 10 | Rev 11 | ||
|---|---|---|---|
| Line 10... | Line 10... | ||
| 10 | #include <sys/stat.h> |
10 | #include <sys/stat.h> |
| 11 | #include <ctype.h> |
11 | #include <ctype.h> |
| 12 | #include <time.h> |
12 | #include <time.h> |
| 13 | 13 | ||
| 14 | 14 | ||
| - | 15 | // compiler-specific glue |
|
| 15 | #ifdef _MSC_VER |
16 | #ifdef _MSC_VER |
| 16 | #include <io.h> |
17 | #include <io.h> |
| 17 | #define __x86_64__ 1 |
18 | #define __x86_64__ 1 |
| 18 | #define __ORDER_BIG_ENDIAN__ 4321 |
19 | #define __ORDER_BIG_ENDIAN__ 4321 |
| 19 | #define __ORDER_LITTLE_ENDIAN__ 1234 |
20 | #define __ORDER_LITTLE_ENDIAN__ 1234 |
| Line 33... | Line 34... | ||
| 33 | #define access(p,m) _access ((p), (m)) |
34 | #define access(p,m) _access ((p), (m)) |
| 34 | #define MAXPATHLEN 1024 |
35 | #define MAXPATHLEN 1024 |
| 35 | #ifndef thread_local |
36 | #ifndef thread_local |
| 36 | #define thread_local __declspec(thread) // the thread_local keyword wasn't defined before C++11 and C23 |
37 | #define thread_local __declspec(thread) // the thread_local keyword wasn't defined before C++11 and C23 |
| 37 | #endif // !thread_local |
38 | #endif // !thread_local |
| - | 39 | #define START_OF_PACKED_STRUCT() __pragma(pack(push)) __pragma(pack(1)) |
|
| - | 40 | #define END_OF_PACKED_STRUCT() __pragma(pack(pop)) |
|
| - | 41 | #define PACKED(thing) thing |
|
| 38 | #else // !_MSC_VER |
42 | #else // !_MSC_VER |
| 39 | #include <sys/param.h> |
43 | #include <sys/param.h> |
| 40 | #include <unistd.h> |
44 | #include <unistd.h> |
| 41 | #ifndef thread_local |
45 | #ifndef thread_local |
| 42 | #define thread_local __thread // the thread_local keyword wasn't defined before C++11 and C23 |
46 | #define thread_local __thread // the thread_local keyword wasn't defined before C++11 and C23 |
| 43 | #endif // !thread_local |
47 | #endif // !thread_local |
| - | 48 | #define START_OF_PACKED_STRUCT() |
|
| - | 49 | #define END_OF_PACKED_STRUCT() |
|
| - | 50 | #define PACKED(thing) thing __attribute__((packed)) |
|
| 44 | #endif // _MSC_VER |
51 | #endif // _MSC_VER |
| 45 | 52 | ||
| 46 | 53 | ||
| 47 | // handy macros that generate a version number in the format "YYYYMMDD" corresponding to the build date. Usage: printf ("version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD); |
54 | // handy macros that generate a version number in the format "YYYYMMDD" corresponding to the build date. Usage: printf ("version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD); |
| 48 | #ifndef VERSION_ARG_YYYYMMDD |
55 | #ifndef VERSION_ARG_YYYYMMDD |
| 49 | #define BUILDDATE_YEAR (&__DATE__[7]) // compiler will optimize this into a const string, e.g. "2021" |
56 | #define BUILDDATE_YEAR (&__DATE__[7]) // compiler will optimize this into a const string, e.g. "2021" |
| - | 57 | #define BUILDDATE_MONTH ( \ |
|
| 50 | |
58 | *((uint32_t *) __DATE__) == *((uint32_t *) "Jan ") ? "01" : \ |
| 51 | |
59 | *((uint32_t *) __DATE__) == *((uint32_t *) "Feb ") ? "02" : \ |
| 52 | |
60 | *((uint32_t *) __DATE__) == *((uint32_t *) "Mar ") ? "03" : \ |
| 53 | |
61 | *((uint32_t *) __DATE__) == *((uint32_t *) "Apr ") ? "04" : \ |
| 54 | |
62 | *((uint32_t *) __DATE__) == *((uint32_t *) "May ") ? "05" : \ |
| 55 | |
63 | *((uint32_t *) __DATE__) == *((uint32_t *) "Jun ") ? "06" : \ |
| 56 | |
64 | *((uint32_t *) __DATE__) == *((uint32_t *) "Jul ") ? "07" : \ |
| 57 | |
65 | *((uint32_t *) __DATE__) == *((uint32_t *) "Aug ") ? "08" : \ |
| 58 | |
66 | *((uint32_t *) __DATE__) == *((uint32_t *) "Sep ") ? "09" : \ |
| 59 | |
67 | *((uint32_t *) __DATE__) == *((uint32_t *) "Oct ") ? "10" : \ |
| 60 | |
68 | *((uint32_t *) __DATE__) == *((uint32_t *) "Nov ") ? "11" : \ |
| 61 | |
69 | *((uint32_t *) __DATE__) == *((uint32_t *) "Dec ") ? "12" : \ |
| - | 70 | "XX" \ |
|
| - | 71 | ) // compiler will optimize this into a const string, e.g. "11" |
|
| - | 72 | #define BUILDDATE_DAY ( \ |
|
| 62 | |
73 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 1 ") ? "01" : \ |
| 63 | |
74 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 2 ") ? "02" : \ |
| 64 | |
75 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 3 ") ? "03" : \ |
| 65 | |
76 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 4 ") ? "04" : \ |
| 66 | |
77 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 5 ") ? "05" : \ |
| 67 | |
78 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 6 ") ? "06" : \ |
| 68 | |
79 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 7 ") ? "07" : \ |
| 69 | |
80 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 8 ") ? "08" : \ |
| 70 | |
81 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 9 ") ? "09" : \ |
| 71 | |
82 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 10 ") ? "10" : \ |
| 72 | |
83 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 11 ") ? "11" : \ |
| 73 | |
84 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 12 ") ? "12" : \ |
| 74 | |
85 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 13 ") ? "13" : \ |
| 75 | |
86 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 14 ") ? "14" : \ |
| 76 | |
87 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 15 ") ? "15" : \ |
| 77 | |
88 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 16 ") ? "16" : \ |
| 78 | |
89 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 17 ") ? "17" : \ |
| 79 | |
90 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 18 ") ? "18" : \ |
| 80 | |
91 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 19 ") ? "19" : \ |
| 81 | |
92 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 20 ") ? "20" : \ |
| 82 | |
93 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 21 ") ? "21" : \ |
| 83 | |
94 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 22 ") ? "22" : \ |
| 84 | |
95 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 23 ") ? "23" : \ |
| 85 | |
96 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 24 ") ? "24" : \ |
| 86 | |
97 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 25 ") ? "25" : \ |
| 87 | |
98 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 26 ") ? "26" : \ |
| 88 | |
99 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 27 ") ? "27" : \ |
| 89 | |
100 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 28 ") ? "28" : \ |
| 90 | |
101 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 29 ") ? "29" : \ |
| 91 | |
102 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 30 ") ? "30" : \ |
| 92 | |
103 | *((uint32_t *) &__DATE__[3]) == *((uint32_t *) " 31 ") ? "31" : \ |
| - | 104 | "XX" \ |
|
| - | 105 | ) // compiler will optimize this into a const string, e.g. "14" |
|
| 93 | #define VERSION_FMT_YYYYMMDD "%04s%02s%02s" |
106 | #define VERSION_FMT_YYYYMMDD "%04s%02s%02s" |
| 94 | #define VERSION_ARG_YYYYMMDD BUILDDATE_YEAR, BUILDDATE_MONTH, BUILDDATE_DAY |
107 | #define VERSION_ARG_YYYYMMDD BUILDDATE_YEAR, BUILDDATE_MONTH, BUILDDATE_DAY |
| 95 | #endif // !VERSION_ARG_YYYYMMDD |
108 | #endif // !VERSION_ARG_YYYYMMDD |
| 96 | 109 | ||
| 97 | 110 | ||
| 98 | // |
111 | // macro to bring __FILE_NAME__ support to moronic compilers |
| - | 112 | #ifndef __FILE_NAME__ // Clang 9+ has the macro, GCC 12+ added it too in 2021, MSVC obviously won't do it. Heh. |
|
| - | 113 | #define __FILE_NAME__ ( \ |
|
| - | 114 | (sizeof (__FILE__) > 2) && (__FILE__[sizeof (__FILE__) - 2] == '/') ? &__FILE__[sizeof (__FILE__) - 1] : \ |
|
| - | 115 | (sizeof (__FILE__) > 3) && (__FILE__[sizeof (__FILE__) - 3] == '/') ? &__FILE__[sizeof (__FILE__) - 2] : \ |
|
| - | 116 | (sizeof (__FILE__) > 4) && (__FILE__[sizeof (__FILE__) - 4] == '/') ? &__FILE__[sizeof (__FILE__) - 3] : \ |
|
| - | 117 | (sizeof (__FILE__) > 5) && (__FILE__[sizeof (__FILE__) - 5] == '/') ? &__FILE__[sizeof (__FILE__) - 4] : \ |
|
| - | 118 | (sizeof (__FILE__) > 6) && (__FILE__[sizeof (__FILE__) - 6] == '/') ? &__FILE__[sizeof (__FILE__) - 5] : \ |
|
| - | 119 | (sizeof (__FILE__) > 7) && (__FILE__[sizeof (__FILE__) - 7] == '/') ? &__FILE__[sizeof (__FILE__) - 6] : \ |
|
| - | 120 | (sizeof (__FILE__) > 8) && (__FILE__[sizeof (__FILE__) - 8] == '/') ? &__FILE__[sizeof (__FILE__) - 7] : \ |
|
| - | 121 | (sizeof (__FILE__) > 9) && (__FILE__[sizeof (__FILE__) - 9] == '/') ? &__FILE__[sizeof (__FILE__) - 8] : \ |
|
| - | 122 | (sizeof (__FILE__) > 10) && (__FILE__[sizeof (__FILE__) - 10] == '/') ? &__FILE__[sizeof (__FILE__) - 9] : \ |
|
| - | 123 | (sizeof (__FILE__) > 11) && (__FILE__[sizeof (__FILE__) - 11] == '/') ? &__FILE__[sizeof (__FILE__) - 10] : \ |
|
| - | 124 | (sizeof (__FILE__) > 12) && (__FILE__[sizeof (__FILE__) - 12] == '/') ? &__FILE__[sizeof (__FILE__) - 11] : \ |
|
| - | 125 | (sizeof (__FILE__) > 13) && (__FILE__[sizeof (__FILE__) - 13] == '/') ? &__FILE__[sizeof (__FILE__) - 12] : \ |
|
| - | 126 | (sizeof (__FILE__) > 14) && (__FILE__[sizeof (__FILE__) - 14] == '/') ? &__FILE__[sizeof (__FILE__) - 13] : \ |
|
| - | 127 | (sizeof (__FILE__) > 15) && (__FILE__[sizeof (__FILE__) - 15] == '/') ? &__FILE__[sizeof (__FILE__) - 14] : \ |
|
| - | 128 | (sizeof (__FILE__) > 16) && (__FILE__[sizeof (__FILE__) - 16] == '/') ? &__FILE__[sizeof (__FILE__) - 15] : \ |
|
| - | 129 | (sizeof (__FILE__) > 17) && (__FILE__[sizeof (__FILE__) - 17] == '/') ? &__FILE__[sizeof (__FILE__) - 16] : \ |
|
| - | 130 | (sizeof (__FILE__) > 18) && (__FILE__[sizeof (__FILE__) - 18] == '/') ? &__FILE__[sizeof (__FILE__) - 17] : \ |
|
| 99 | |
131 | (sizeof (__FILE__) > 19) && (__FILE__[sizeof (__FILE__) - 19] == '/') ? &__FILE__[sizeof (__FILE__) - 18] : \ |
| - | 132 | (sizeof (__FILE__) > 20) && (__FILE__[sizeof (__FILE__) - 20] == '/') ? &__FILE__[sizeof (__FILE__) - 19] : \ |
|
| - | 133 | (sizeof (__FILE__) > 21) && (__FILE__[sizeof (__FILE__) - 21] == '/') ? &__FILE__[sizeof (__FILE__) - 20] : \ |
|
| - | 134 | (sizeof (__FILE__) > 22) && (__FILE__[sizeof (__FILE__) - 22] == '/') ? &__FILE__[sizeof (__FILE__) - 21] : \ |
|
| - | 135 | (sizeof (__FILE__) > 23) && (__FILE__[sizeof (__FILE__) - 23] == '/') ? &__FILE__[sizeof (__FILE__) - 22] : \ |
|
| - | 136 | (sizeof (__FILE__) > 24) && (__FILE__[sizeof (__FILE__) - 24] == '/') ? &__FILE__[sizeof (__FILE__) - 23] : \ |
|
| - | 137 | (sizeof (__FILE__) > 25) && (__FILE__[sizeof (__FILE__) - 25] == '/') ? &__FILE__[sizeof (__FILE__) - 24] : \ |
|
| - | 138 | (sizeof (__FILE__) > 26) && (__FILE__[sizeof (__FILE__) - 26] == '/') ? &__FILE__[sizeof (__FILE__) - 25] : \ |
|
| - | 139 | (sizeof (__FILE__) > 27) && (__FILE__[sizeof (__FILE__) - 27] == '/') ? &__FILE__[sizeof (__FILE__) - 26] : \ |
|
| - | 140 | (sizeof (__FILE__) > 28) && (__FILE__[sizeof (__FILE__) - 28] == '/') ? &__FILE__[sizeof (__FILE__) - 27] : \ |
|
| - | 141 | (sizeof (__FILE__) > 29) && (__FILE__[sizeof (__FILE__) - 29] == '/') ? &__FILE__[sizeof (__FILE__) - 28] : \ |
|
| - | 142 | (sizeof (__FILE__) > 30) && (__FILE__[sizeof (__FILE__) - 30] == '/') ? &__FILE__[sizeof (__FILE__) - 29] : \ |
|
| - | 143 | (sizeof (__FILE__) > 31) && (__FILE__[sizeof (__FILE__) - 31] == '/') ? &__FILE__[sizeof (__FILE__) - 30] : \ |
|
| - | 144 | (sizeof (__FILE__) > 32) && (__FILE__[sizeof (__FILE__) - 32] == '/') ? &__FILE__[sizeof (__FILE__) - 31] : \ |
|
| - | 145 | (sizeof (__FILE__) > 33) && (__FILE__[sizeof (__FILE__) - 33] == '/') ? &__FILE__[sizeof (__FILE__) - 32] : \ |
|
| - | 146 | __FILE__) // this *COMPILE-TIME* macro complements the __FILE__ macro defined by the C standard by returning just the filename portion of the full path. Supports filenames up to 32 chars. Expand as necessary. |
|
| - | 147 | #endif // !__FILE_NAME__ |
|
| 100 | 148 | ||
| 101 | 149 | ||
| 102 | // exit less brutally than with abort() if something doesn't go the way we'd like to |
150 | // macro to exit less brutally than with abort() if something doesn't go the way we'd like to |
| 103 | #define WELLMANNERED_ASSERT(is_is_true,...) do { if (!(is_is_true)) { fprintf (stderr, "ifstool: fatal error: |
151 | #define WELLMANNERED_ASSERT(is_is_true,...) do { if (!(is_is_true)) { fprintf (stderr, "ifstool: fatal error: consistency check in %s() at %s line %d failed: ", __FUNCTION__, __FILE_NAME__, __LINE__); fprintf (stderr, __VA_ARGS__); fputc ('\n', stderr); exit (1); } } while (0) |
| 104 | 152 | ||
| 105 | 153 | ||
| 106 | // checked read/write/seek operations |
154 | // macros for checked read/write/seek operations |
| 107 | #define fseek_or_die(fp,pos,mode) |
155 | #define fseek_or_die(fp,pos,mode) WELLMANNERED_ASSERT (fseek ((fp), (pos), (mode)) == 0, "fseek() failed with errno %d (%s)", errno, strerror (errno)) |
| 108 | #define fread_or_die(buf,sz,len,fp) |
156 | #define fread_or_die(buf,sz,len,fp) WELLMANNERED_ASSERT (fread ((buf), (sz), (len), (fp)) == (len), "fread() failed with errno %d (%s)", errno, strerror (errno)) |
| 109 | #define fwrite_or_die(buf,sz,len,fp) |
157 | #define fwrite_or_die(buf,sz,len,fp) WELLMANNERED_ASSERT ((fwrite ((buf), (sz), (len), (fp)) == (len)) && (fflush ((fp)) == 0), "flushed fwrite() failed with errno %d (%s)", errno, strerror (errno)) |
| 110 | 158 | ||
| 111 | - | ||
| 112 | #define ROUND_TO_UPPER_MULTIPLE(val,multiple) ((((val) + (size_t) (multiple) - 1) / (multiple)) * (multiple)) // note that val is being evaluated once, so it can be the result of a function call |
- | |
| 113 | #ifdef _WIN32 |
- | |
| 114 | #define IS_DIRSEP(c) (((c) == '/') || ((c) == '\\')) |
- | |
| 115 | #define PATH_SEP ';' |
- | |
| 116 | #define PATH_SEP_STR ";" |
- | |
| 117 | #else // !_WIN32, thus POSIX |
- | |
| 118 | #define IS_DIRSEP(c) ((c) == '/') |
- | |
| 119 | #define PATH_SEP ':' |
- | |
| 120 | #define PATH_SEP_STR ":" |
- | |
| 121 | #endif // _WIN32 |
- | |
| 122 | #define RECORD_SEP '\x1e' // ASCII record separator |
- | |
| 123 | #define RECORD_SEP_STR "\x1e" // ASCII record separator (as string) |
- | |
| 124 | 159 | ||
| 125 | // macros for accessing ELF files |
160 | // macros for accessing ELF files |
| 126 | #define ELF_MAGIC_STR "\x7f" "ELF" |
161 | #define ELF_MAGIC_STR "\x7f" "ELF" |
| 127 | #define ELF_ENDIAN_LITTLE 1 // 'endianness' member of an ELF header: ELF file is little endian |
162 | #define ELF_ENDIAN_LITTLE 1 // 'endianness' member of an ELF header: ELF file is little endian |
| 128 | #define ELF_ENDIAN_BIG 2 // 'endianness' member of an ELF header: ELF file is big endian |
163 | #define ELF_ENDIAN_BIG 2 // 'endianness' member of an ELF header: ELF file is big endian |
| Line 164... | Line 199... | ||
| 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 |
199 | #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 |
200 | #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 |
| 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 |
201 | #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 | 202 | ||
| 168 | 203 | ||
| 169 | - | ||
| - | 204 | // placeholder value |
|
| 170 | #define WILL_BE_FILLED_LATER 0xbaadf00d |
205 | #define WILL_BE_FILLED_LATER 0xbaadf00d // urgh |
| 171 | 206 | ||
| 172 | 207 | ||
| 173 | // bitmapped flags used in the flags1 member of the startup header |
208 | // bitmapped flags used in the flags1 member of the startup header |
| 174 | #define STARTUP_HDR_FLAGS1_VIRTUAL (1 << 0) |
209 | #define STARTUP_HDR_FLAGS1_VIRTUAL (1 << 0) |
| 175 | #define STARTUP_HDR_FLAGS1_BIGENDIAN (1 << 1) |
210 | #define STARTUP_HDR_FLAGS1_BIGENDIAN (1 << 1) |
| Line 192... | Line 227... | ||
| 192 | 227 | ||
| 193 | // bitmapped flags superposed to a filesystem entry's inode number |
228 | // bitmapped flags superposed to a filesystem entry's inode number |
| 194 | #define IFS_INO_PROCESSED_ELF 0x80000000 |
229 | #define IFS_INO_PROCESSED_ELF 0x80000000 |
| 195 | #define IFS_INO_RUNONCE_ELF 0x40000000 |
230 | #define IFS_INO_RUNONCE_ELF 0x40000000 |
| 196 | #define IFS_INO_BOOTSTRAP_EXE 0x20000000 |
231 | #define IFS_INO_BOOTSTRAP_EXE 0x20000000 |
| - | 232 | ||
| - | 233 | ||
| - | 234 | // miscellaneous macros |
|
| - | 235 | #define ROUND_TO_UPPER_MULTIPLE(val,multiple) ((((val) + (size_t) (multiple) - 1) / (multiple)) * (multiple)) // note that val is being evaluated once, so it can be the result of a function call |
|
| - | 236 | #ifdef _WIN32 |
|
| - | 237 | #define IS_DIRSEP(c) (((c) == '/') || ((c) == '\\')) // platform-specific directory separator, Win32 variant |
|
| - | 238 | #define PATH_SEP ';' // platform-specific PATH element separator, Win32 variant |
|
| - | 239 | #define PATH_SEP_STR ";" // platform-specific PATH element separator (as string), Win32 variant |
|
| - | 240 | #else // !_WIN32, thus POSIX |
|
| - | 241 | #define IS_DIRSEP(c) ((c) == '/') // platform-specific directory separator, UNIX variant |
|
| - | 242 | #define PATH_SEP ':' // platform-specific PATH element separator, UNIX variant |
|
| - | 243 | #define PATH_SEP_STR ":" // platform-specific PATH element separator (as string), UNIX variant |
|
| - | 244 | #endif // _WIN32 |
|
| - | 245 | #define RECORD_SEP '\x1e' // arbitrarily-chosen ASCII record separator |
|
| - | 246 | #define RECORD_SEP_STR "\x1e" // arbitrarily-chosen ASCII record separator (as string) |
|
| 197 | 247 | ||
| 198 | 248 | ||
| 199 | // SHA-512 block and digest sizes |
249 | // SHA-512 block and digest sizes |
| 200 | #define SHA512_BLOCK_LENGTH 128 // in bytes |
250 | #define SHA512_BLOCK_LENGTH 128 // in bytes |
| 201 | #define SHA512_DIGEST_LENGTH 64 // in bytes |
251 | #define SHA512_DIGEST_LENGTH 64 // in bytes |
| Line 206... | Line 256... | ||
| 206 | { |
256 | { |
| 207 | uint64_t state[8]; |
257 | uint64_t state[8]; |
| 208 | uint64_t bitcount[2]; |
258 | uint64_t bitcount[2]; |
| 209 | uint8_t buffer[SHA512_BLOCK_LENGTH]; |
259 | uint8_t buffer[SHA512_BLOCK_LENGTH]; |
| 210 | } SHA512_CTX; |
260 | } SHA512_CTX; |
| 211 | - | ||
| 212 | - | ||
| 213 | #ifdef _MSC_VER |
- | |
| 214 | #pragma pack(push) |
- | |
| 215 | #pragma pack(1) |
- | |
| 216 | #endif // _MSC_VER |
- | |
| 217 | 261 | ||
| 218 | 262 | ||
| 219 | #if 0 // TODO: startup script compiler. Someday. |
263 | #if 0 // TODO: startup script compiler. Someday. |
| 220 | #define SCRIPT_FLAGS_EXTSCHED 0x01 |
264 | #define SCRIPT_FLAGS_EXTSCHED 0x01 |
| 221 | #define SCRIPT_FLAGS_SESSION 0x02 |
265 | #define SCRIPT_FLAGS_SESSION 0x02 |
| Line 245... | Line 289... | ||
| 245 | #define SCRIPT_APS_SYSTEM_PARTITION_NAME "System" |
289 | #define SCRIPT_APS_SYSTEM_PARTITION_NAME "System" |
| 246 | #define SCRIPT_APS_PARTITION_NAME_LENGTH 15 |
290 | #define SCRIPT_APS_PARTITION_NAME_LENGTH 15 |
| 247 | #define SCRIPT_APS_MAX_PARTITIONS 8 |
291 | #define SCRIPT_APS_MAX_PARTITIONS 8 |
| 248 | 292 | ||
| 249 | 293 | ||
| - | 294 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 250 | typedef |
295 | typedef PACKED (struct) bootscriptcmd_header_s |
| 251 | { |
296 | { |
| 252 | uint16_t size; // size of cmd entry |
297 | uint16_t size; // size of cmd entry |
| 253 | uint8_t type; |
298 | uint8_t type; |
| 254 | uint8_t spare; |
299 | uint8_t spare; |
| 255 | } bootscriptcmd_header_t; |
300 | } bootscriptcmd_header_t; |
| - | 301 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 256 | 302 | ||
| 257 | 303 | ||
| - | 304 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 258 | typedef union bootscriptcmd_s |
305 | typedef union bootscriptcmd_s |
| 259 | { |
306 | { |
| 260 |
|
307 | PACKED (struct) script_external |
| 261 | { |
308 | { |
| 262 | bootscriptcmd_header_t hdr; |
309 | bootscriptcmd_header_t hdr; |
| 263 | uint8_t cpu; // CPU (turn into runmask) |
310 | uint8_t cpu; // CPU (turn into runmask) |
| 264 | uint8_t flags; |
311 | uint8_t flags; |
| 265 | union script_external_extsched |
312 | union script_external_extsched |
| 266 | { |
313 | { |
| 267 | uint8_t reserved[2]; |
314 | uint8_t reserved[2]; |
| 268 |
|
315 | PACKED (struct) |
| 269 | { |
316 | { |
| 270 | uint8_t id; |
317 | uint8_t id; |
| 271 | uint8_t reserved[1]; |
318 | uint8_t reserved[1]; |
| 272 | } aps; |
319 | } aps; |
| 273 | } extsched; // extended scheduler |
320 | } extsched; // extended scheduler |
| Line 275... | Line 322... | ||
| 275 | uint8_t priority; // priority to run cmd at |
322 | uint8_t priority; // priority to run cmd at |
| 276 | uint8_t argc; // # of args |
323 | uint8_t argc; // # of args |
| 277 | uint8_t envc; // # of environment entries |
324 | uint8_t envc; // # of environment entries |
| 278 | char args[0]; // executable, argv, envp (null padded to 32-bit align) |
325 | char args[0]; // executable, argv, envp (null padded to 32-bit align) |
| 279 | } external; |
326 | } external; |
| 280 |
|
327 | PACKED (struct) script_waitfor_reopen |
| 281 | { |
328 | { |
| 282 | bootscriptcmd_header_t hdr; |
329 | bootscriptcmd_header_t hdr; |
| 283 | uint16_t checks; |
330 | uint16_t checks; |
| 284 | char fname[0]; // char fname[] (null padded to 32-bit align) |
331 | char fname[0]; // char fname[] (null padded to 32-bit align) |
| 285 | } waitfor_reopen; |
332 | } waitfor_reopen; |
| 286 |
|
333 | PACKED (struct) script_display_msg |
| 287 | { |
334 | { |
| 288 | bootscriptcmd_header_t hdr; |
335 | bootscriptcmd_header_t hdr; |
| 289 | char msg[0]; // char msg[] (null padded to 32-bit align) |
336 | char msg[0]; // char msg[] (null padded to 32-bit align) |
| 290 | } display_msg; |
337 | } display_msg; |
| 291 |
|
338 | PACKED (struct) script_procmgr_symlink |
| 292 | { |
339 | { |
| 293 | bootscriptcmd_header_t hdr; |
340 | bootscriptcmd_header_t hdr; |
| 294 | char src_dest[0]; // <src_name>, '\0', <dest_name> '\0' (null padded to 32-bit align) |
341 | char src_dest[0]; // <src_name>, '\0', <dest_name> '\0' (null padded to 32-bit align) |
| 295 | } procmgr_symlink; |
342 | } procmgr_symlink; |
| 296 |
|
343 | PACKED (struct) script_extsched_aps |
| 297 | { |
344 | { |
| 298 | bootscriptcmd_header_t hdr; |
345 | bootscriptcmd_header_t hdr; |
| 299 | uint8_t parent; |
346 | uint8_t parent; |
| 300 | uint8_t budget; |
347 | uint8_t budget; |
| 301 | uint16_t critical; |
348 | uint16_t critical; |
| 302 | uint8_t id; |
349 | uint8_t id; |
| 303 | char pname[0]; // char pname[] (null padded to 32-bit align) |
350 | char pname[0]; // char pname[] (null padded to 32-bit align) |
| 304 | } extsched_aps; |
351 | } extsched_aps; |
| 305 | } bootscriptcmd_t; |
352 | } bootscriptcmd_t; |
| - | 353 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 306 | #endif // 0 |
354 | #endif // 0 |
| 307 | 355 | ||
| 308 | 356 | ||
| 309 | #define INITIAL_STARTUP_SCRIPT \ |
357 | #define INITIAL_STARTUP_SCRIPT \ |
| 310 | /* procmgr_symlink /proc/boot/ldqnx-64.so.2 /usr/lib/ldqnx-64.so.2 */ \ |
358 | /* procmgr_symlink /proc/boot/ldqnx-64.so.2 /usr/lib/ldqnx-64.so.2 */ \ |
| Line 315... | Line 363... | ||
| 315 | "\x18\x00" /*size*/ "\x03" /*type*/ "\x00" /*spare*/ "Startup complete\n\0" "\x00\00" /*padding*/ \ |
363 | "\x18\x00" /*size*/ "\x03" /*type*/ "\x00" /*spare*/ "Startup complete\n\0" "\x00\00" /*padding*/ \ |
| 316 | /* trailer */ \ |
364 | /* trailer */ \ |
| 317 | "\x00\x00\x00\x00" |
365 | "\x00\x00\x00\x00" |
| 318 | 366 | ||
| 319 | 367 | ||
| - | 368 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 320 | typedef |
369 | typedef PACKED (struct) fsentry_s |
| 321 | { |
370 | { |
| 322 |
|
371 | PACKED (struct) fsentry_header_s |
| 323 | { |
372 | { |
| 324 | uint16_t size; // size of dirent |
373 | uint16_t size; // size of dirent |
| 325 | uint16_t extattr_offset; // if zero, no extattr data |
374 | uint16_t extattr_offset; // if zero, no extattr data |
| 326 | uint32_t ino; // if zero, skip entry |
375 | uint32_t ino; // if zero, skip entry |
| 327 | uint32_t mode; // mode and perms of entry |
376 | uint32_t mode; // mode and perms of entry |
| 328 | uint32_t gid; |
377 | uint32_t gid; |
| 329 | uint32_t uid; |
378 | uint32_t uid; |
| 330 | uint32_t mtime; |
379 | uint32_t mtime; |
| 331 | } header; |
380 | } header; |
| 332 |
|
381 | PACKED (union) fsentry_specific_u |
| 333 | { |
382 | { |
| 334 |
|
383 | PACKED (struct) fsentry_file_s // when (mode & S_IFMT) == S_IFREG |
| 335 | { |
384 | { |
| 336 | uint32_t offset; // offset from header |
385 | uint32_t offset; // offset from header |
| 337 | uint32_t size; |
386 | uint32_t size; |
| 338 | char *path; // null terminated path (no leading slash) |
387 | char *path; // null terminated path (no leading slash) |
| 339 | char *UNSAVED_databuf; // file data blob buffer (NOT SAVED IN THE IFS) |
388 | char *UNSAVED_databuf; // file data blob buffer (NOT SAVED IN THE IFS) |
| 340 | } file; |
389 | } file; |
| 341 |
|
390 | PACKED (struct) fsentry_dir_s // when (mode & S_IFMT) == S_IFDIR |
| 342 | { |
391 | { |
| 343 | char *path; // null terminated path (no leading slash) |
392 | char *path; // null terminated path (no leading slash) |
| 344 | } dir; |
393 | } dir; |
| 345 |
|
394 | PACKED (struct) fsentry_symlink_s // when (mode & S_IFMT) == S_IFLNK |
| 346 | { |
395 | { |
| 347 | uint16_t sym_offset; // offset to 'contents' from 'path' |
396 | uint16_t sym_offset; // offset to 'contents' from 'path' |
| 348 | uint16_t sym_size; // strlen (contents) |
397 | uint16_t sym_size; // strlen (contents) |
| 349 | char *path; // null terminated path (no leading slash) |
398 | char *path; // null terminated path (no leading slash) |
| 350 | char *contents; // null terminated symlink contents |
399 | char *contents; // null terminated symlink contents |
| 351 | } symlink; |
400 | } symlink; |
| 352 |
|
401 | PACKED (struct) fsentry_device_s // when (mode & S_IFMT) == S_IF<CHR|BLK|FIFO|NAM|SOCK> |
| 353 | { |
402 | { |
| 354 | uint32_t dev; |
403 | uint32_t dev; |
| 355 | uint32_t rdev; |
404 | uint32_t rdev; |
| 356 | char *path; // null terminated path (no leading slash) |
405 | char *path; // null terminated path (no leading slash) |
| 357 | } device; |
406 | } device; |
| 358 | } u; |
407 | } u; |
| 359 | bool UNSAVED_was_data_written; // whether this entry's data was written to the image (NOT SAVED IN THE IFS) |
408 | bool UNSAVED_was_data_written; // whether this entry's data was written to the image (NOT SAVED IN THE IFS) |
| 360 | } fsentry_t; |
409 | } fsentry_t; |
| - | 410 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 361 | 411 | ||
| 362 | 412 | ||
| - | 413 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 363 | typedef |
414 | typedef PACKED (struct) startup_header_s // size 256 bytes |
| 364 | { |
415 | { |
| 365 |
|
416 | // I - used by the QNX IPL |
| 366 |
|
417 | // S - used by the startup program |
| 367 | uint8_t signature[4]; // [I ] Header signature, "\xeb\x7e\xff\x00" |
418 | uint8_t signature[4]; // [I ] Header signature, "\xeb\x7e\xff\x00" |
| 368 | uint16_t version; // [I ] Header version, i.e. 1 |
419 | uint16_t version; // [I ] Header version, i.e. 1 |
| 369 | uint8_t flags1; // [IS] Misc flags, 0x21 (= 0x20 | STARTUP_HDR_FLAGS1_VIRTUAL) |
420 | uint8_t flags1; // [IS] Misc flags, 0x21 (= 0x20 | STARTUP_HDR_FLAGS1_VIRTUAL) |
| 370 | uint8_t flags2; // [ ] No flags defined yet (0) |
421 | uint8_t flags2; // [ ] No flags defined yet (0) |
| 371 | uint16_t header_size; // [ S] sizeof(struct startup_header), i.e. 256 |
422 | uint16_t header_size; // [ S] sizeof(struct startup_header), i.e. 256 |
| Line 383... | Line 434... | ||
| 383 | uint16_t zero0; // [ ] Zeros |
434 | uint16_t zero0; // [ ] Zeros |
| 384 | uint32_t zero[1]; // [ ] Zeros |
435 | uint32_t zero[1]; // [ ] Zeros |
| 385 | uint64_t addr_off; // [ S] Offset to add to startup_vaddr, image_paddr, ram_paddr, and imagefs_paddr members, here zero (0) |
436 | uint64_t addr_off; // [ S] Offset to add to startup_vaddr, image_paddr, ram_paddr, and imagefs_paddr members, here zero (0) |
| 386 | uint32_t info[48]; // [IS] Array of startup_info* structures (zero filled) |
437 | uint32_t info[48]; // [IS] Array of startup_info* structures (zero filled) |
| 387 | } startup_header_t; |
438 | } startup_header_t; |
| - | 439 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 388 | 440 | ||
| 389 | 441 | ||
| - | 442 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 390 | typedef |
443 | typedef PACKED (struct) startup_trailer_s |
| 391 | { |
444 | { |
| 392 | uint32_t cksum; // checksum from start of header to start of trailer |
445 | uint32_t cksum; // checksum from start of header to start of trailer |
| 393 | } startup_trailer_v1_t; |
446 | } startup_trailer_v1_t; |
| - | 447 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 394 | 448 | ||
| 395 | 449 | ||
| 396 | // NOTE: The checksums in this trailer will only be valid prior to entering startup. |
450 | // NOTE: The checksums in this trailer will only be valid prior to entering startup. |
| 397 | // Because the startup binary is executed in-place, its data segment will change once the program is running. |
451 | // Because the startup binary is executed in-place, its data segment will change once the program is running. |
| 398 | // Hence, any checksum validation would need to be done by the boot loader / IFS. |
452 | // Hence, any checksum validation would need to be done by the boot loader / IFS. |
| - | 453 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 399 | typedef |
454 | typedef PACKED (struct) startup_trailer_v2_s |
| 400 | { |
455 | { |
| 401 | uint8_t sha512[64]; // SHA512 from start of header to start of trailer |
456 | uint8_t sha512[64]; // SHA512 from start of header to start of trailer |
| 402 | uint32_t cksum; // checksum from start of header to start of this member |
457 | uint32_t cksum; // checksum from start of header to start of this member |
| 403 | } startup_trailer_v2_t; |
458 | } startup_trailer_v2_t; |
| - | 459 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 404 | 460 | ||
| 405 | 461 | ||
| - | 462 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 406 | typedef |
463 | typedef PACKED (struct) image_header_s |
| 407 | { |
464 | { |
| 408 | uint8_t signature[7]; // image filesystem signature, i.e. "imagefs" |
465 | uint8_t signature[7]; // image filesystem signature, i.e. "imagefs" |
| 409 | uint8_t flags; // endian neutral flags, 0x1c |
466 | uint8_t flags; // endian neutral flags, 0x1c |
| 410 | uint32_t image_size; // size from start of header to end of trailer (here 0xca6fe0 or 13 266 912) |
467 | uint32_t image_size; // size from start of header to end of trailer (here 0xca6fe0 or 13 266 912) |
| 411 | uint32_t hdr_dir_size; // size from start of header to last dirent (here 0x12b8 or 4792) |
468 | uint32_t hdr_dir_size; // size from start of header to last dirent (here 0x12b8 or 4792) |
| Line 415... | Line 472... | ||
| 415 | uint32_t chain_paddr; // offset to next filesystem signature (0) |
472 | uint32_t chain_paddr; // offset to next filesystem signature (0) |
| 416 | uint32_t spare[10]; // zerofill |
473 | uint32_t spare[10]; // zerofill |
| 417 | uint32_t mountflags; // default _MOUNT_* from sys/iomsg.h (0) |
474 | uint32_t mountflags; // default _MOUNT_* from sys/iomsg.h (0) |
| 418 | char mountpoint[4]; // default mountpoint for image ("/" + "\0\0\0") |
475 | char mountpoint[4]; // default mountpoint for image ("/" + "\0\0\0") |
| 419 | } image_header_t; |
476 | } image_header_t; |
| - | 477 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 420 | 478 | ||
| 421 | 479 | ||
| - | 480 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 422 | typedef |
481 | typedef PACKED (struct) image_trailer_v1_s |
| 423 | { |
482 | { |
| 424 | uint32_t cksum; // checksum from start of header to start of trailer |
483 | uint32_t cksum; // checksum from start of header to start of trailer |
| 425 | } image_trailer_v1_t; // NOTE: this is the same structure as startup_trailer_v1_t |
484 | } image_trailer_v1_t; // NOTE: this is the same structure as startup_trailer_v1_t |
| - | 485 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 426 | 486 | ||
| 427 | 487 | ||
| 428 | // NOTE: the checksums in this trailer will only be valid until the first non-startup bootstrap binary (e.g., startup-verifier, procnto, ...) is invoked. |
488 | // NOTE: the checksums in this trailer will only be valid until the first non-startup bootstrap binary (e.g., startup-verifier, procnto, ...) is invoked. |
| 429 | // Because bootstrap binaries execute in-place, their data segments will change once the programs are running. |
489 | // Because bootstrap binaries execute in-place, their data segments will change once the programs are running. |
| 430 | // Hence, any checksum validation would need to be done either by the boot loader / IFS or by the startup. |
490 | // Hence, any checksum validation would need to be done either by the boot loader / IFS or by the startup. |
| - | 491 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 431 | typedef |
492 | typedef PACKED (struct) image_trailer_v2_s |
| 432 | { |
493 | { |
| 433 | uint8_t sha512[64]; // SHA512 from start of image header to start of trailer |
494 | uint8_t sha512[64]; // SHA512 from start of image header to start of trailer |
| 434 | uint32_t cksum; // checksum from start of header to start of this member |
495 | uint32_t cksum; // checksum from start of header to start of this member |
| 435 | } image_trailer_v2_t; // NOTE: this is the same structure as startup_trailer_v2_t |
496 | } image_trailer_v2_t; // NOTE: this is the same structure as startup_trailer_v2_t |
| - | 497 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 436 | 498 | ||
| 437 | 499 | ||
| 438 | // Executable and Linkable Format master header structure type definition |
500 | // Executable and Linkable Format master header structure type definition |
| - | 501 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 439 | typedef |
502 | typedef PACKED (struct) elf_header_s |
| 440 | { |
503 | { |
| 441 |
|
504 | PACKED (union) |
| 442 | { |
505 | { |
| 443 |
|
506 | PACKED (struct) |
| 444 | { |
507 | { |
| 445 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
508 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
| 446 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
509 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
| 447 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
510 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
| 448 | uint8_t header_version; // offset 6: typically 1 |
511 | uint8_t header_version; // offset 6: typically 1 |
| Line 450... | Line 513... | ||
| 450 | uint8_t spare[8]; // offset 8: zeroes |
513 | uint8_t spare[8]; // offset 8: zeroes |
| 451 | uint16_t type; // offset 16: 1 = relocatable, 2 = executable, 3 = shared, 4 = core dump |
514 | uint16_t type; // offset 16: 1 = relocatable, 2 = executable, 3 = shared, 4 = core dump |
| 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 |
515 | 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 |
| 453 | uint32_t elf_version; // offset 20: typically 1 |
516 | uint32_t elf_version; // offset 20: typically 1 |
| 454 | } elf; |
517 | } elf; |
| 455 |
|
518 | PACKED (struct) // size == 52 |
| 456 | { |
519 | { |
| 457 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
520 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
| 458 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
521 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
| 459 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
522 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
| 460 | uint8_t header_version; // offset 6: typically 1 |
523 | uint8_t header_version; // offset 6: typically 1 |
| Line 472... | Line 535... | ||
| 472 | uint16_t program_header_table_len; // offset 44: number of entries in the program header table |
535 | uint16_t program_header_table_len; // offset 44: number of entries in the program header table |
| 473 | uint16_t section_header_item_size; // offset 46: size of an entry in the section header table |
536 | uint16_t section_header_item_size; // offset 46: size of an entry in the section header table |
| 474 | uint16_t section_header_table_len; // offset 48: number of entries in the section header table |
537 | uint16_t section_header_table_len; // offset 48: number of entries in the section header table |
| 475 | uint16_t section_header_names_idx; // offset 50: index of the entry in the section header table that contains the section names |
538 | uint16_t section_header_names_idx; // offset 50: index of the entry in the section header table that contains the section names |
| 476 | } elf32; // size == 52 |
539 | } elf32; // size == 52 |
| 477 |
|
540 | PACKED (struct) // size == 64 |
| 478 | { |
541 | { |
| 479 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
542 | uint8_t magic[4]; // offset 0: "\x7f" + "ELF" |
| 480 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
543 | uint8_t platform_size; // offset 4: 1 = 32-bit, 2 = 64-bit |
| 481 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
544 | uint8_t endianness; // offset 5: 1 = little endian, 2 = big endian |
| 482 | uint8_t header_version; // offset 6: typically 1 |
545 | uint8_t header_version; // offset 6: typically 1 |
| Line 496... | Line 559... | ||
| 496 | uint16_t section_header_table_len; // offset 60: number of entries in the section header table |
559 | uint16_t section_header_table_len; // offset 60: number of entries in the section header table |
| 497 | uint16_t section_header_names_idx; // offset 62: index of the entry in the section header table that contains the section names |
560 | uint16_t section_header_names_idx; // offset 62: index of the entry in the section header table that contains the section names |
| 498 | } elf64; // size == 64 |
561 | } elf64; // size == 64 |
| 499 | } u; |
562 | } u; |
| 500 | } elf_header_t; |
563 | } elf_header_t; |
| - | 564 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 501 | 565 | ||
| 502 | 566 | ||
| 503 | // Executable and Linkable Format program header structure type definition |
567 | // Executable and Linkable Format program header structure type definition |
| - | 568 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 504 | typedef |
569 | typedef PACKED (struct) elf_program_header_s |
| 505 | { |
570 | { |
| 506 |
|
571 | PACKED (union) |
| 507 | { |
572 | { |
| 508 |
|
573 | PACKED (struct) |
| 509 | { |
574 | { |
| 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) |
575 | 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; |
576 | } elf; |
| 512 |
|
577 | PACKED (struct) // size == 32 |
| 513 | { |
578 | { |
| 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) |
579 | 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 |
580 | 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 |
581 | 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 |
582 | 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) |
583 | 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) |
584 | 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) |
585 | 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) |
586 | 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 |
587 | } elf32; // size == 32 |
| 523 |
|
588 | PACKED (struct) // size == 56 |
| 524 | { |
589 | { |
| 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) |
590 | 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) |
591 | 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 |
592 | 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 |
593 | uint64_t virtual_addr; // offset 16: virtual address where this segment should be mapped in memory |
| Line 531... | Line 596... | ||
| 531 | uint64_t size_in_memory; // offset 40: size of this segment in memory (may be zero) |
596 | 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) |
597 | 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 |
598 | } elf64; // size == 56 |
| 534 | } u; |
599 | } u; |
| 535 | } elf_program_header_t; |
600 | } elf_program_header_t; |
| - | 601 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 536 | 602 | ||
| 537 | 603 | ||
| 538 | // Executable and Linkable Format section header structure type definition |
604 | // Executable and Linkable Format section header structure type definition |
| - | 605 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 539 | typedef |
606 | typedef PACKED (struct) elf_section_header_s |
| 540 | { |
607 | { |
| 541 |
|
608 | PACKED (union) |
| 542 | { |
609 | { |
| - | 610 | PACKED (struct) |
|
| - | 611 | { |
|
| - | 612 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
|
| 543 |
|
613 | uint32_t type; // offset 4: section type (0: unused, 1: program data, 2: symbols table, 3: strings table, 4: relocs with addends, 5: symbols hash table, 6: dyld info, 7: notes, 8: BSS, 9: relocs without addends, 11: dyld symbols table, 14: constructors, 15: destructors, 16, preconstructors, 17: group, 18: extended section indices, 19: number of typedefs ...) |
| - | 614 | } elf; |
|
| - | 615 | PACKED (struct) // size == 40 |
|
| 544 | { |
616 | { |
| 545 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
617 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
| 546 | uint32_t type; // offset 4: |
618 | uint32_t type; // offset 4: section type (0: unused, 1: program data, 2: symbols table, 3: strings table, 4: relocs with addends, 5: symbols hash table, 6: dyld info, 7: notes, 8: BSS, 9: relocs without addends, 11: dyld symbols table, 14: constructors, 15: destructors, 16, preconstructors, 17: group, 18: extended section indices, 19: number of typedefs ...) |
| 547 | uint32_t flags; // offset 8: |
619 | uint32_t flags; // offset 8: bitmapped flags (1: writable, 2: takes RAM, 4: executable, 8: reserved, 16: mergeable, 32: contains C-strings, 64: sh_info contains SHT index, 128: preserve order, 256: OS-specific, 512: group member, 1024: TLS template ...) |
| 548 | uint32_t virtual_addr; // offset 12: address in virtual memory where this section may be loaded |
620 | uint32_t virtual_addr; // offset 12: address in virtual memory where this section may be loaded |
| 549 | uint32_t file_offset; // offset 16: offset of this section in the ELF file |
621 | uint32_t file_offset; // offset 16: offset of this section in the ELF file |
| 550 | uint32_t size; // offset 20: size of this section |
622 | uint32_t size; // offset 20: size of this section |
| 551 | uint32_t linked_index; // offset 24: optional section index of an associated section |
623 | uint32_t linked_index; // offset 24: optional section index of an associated section |
| 552 | uint32_t info; // offset 28: optional extra information |
624 | uint32_t info; // offset 28: optional extra information |
| 553 | uint32_t alignment; // offset 32: required memory alignment (must be a power of 2) |
625 | uint32_t alignment; // offset 32: required memory alignment (must be a power of 2) |
| 554 | uint32_t entry_size; // offset 36: for table-like sections, size of an element in the table |
626 | uint32_t entry_size; // offset 36: for table-like sections, size of an element in the table |
| 555 | } elf32; // size == 40 |
627 | } elf32; // size == 40 |
| 556 |
|
628 | PACKED (struct) // size == 64 |
| 557 | { |
629 | { |
| 558 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
630 | uint32_t name_offset; // offset 0: offset in the string table of the name of this section |
| 559 | uint32_t type; // offset 4: |
631 | uint32_t type; // offset 4: section type (0: unused, 1: program data, 2: symbols table, 3: strings table, 4: relocs with addends, 5: symbols hash table, 6: dyld info, 7: notes, 8: BSS, 9: relocs without addends, 11: dyld symbols table, 14: constructors, 15: destructors, 16, preconstructors, 17: group, 18: extended section indices, 19: number of typedefs ...) |
| 560 | uint64_t flags; // offset 8: |
632 | uint64_t flags; // offset 8: bitmapped flags (1: writable, 2: takes RAM, 4: executable, 8: reserved, 16: mergeable, 32: contains C-strings, 64: sh_info contains SHT index, 128: preserve order, 256: OS-specific, 512: group member, 1024: TLS template ...) |
| 561 | uint64_t virtual_addr; // offset 16: address in virtual memory where this section may be loaded |
633 | uint64_t virtual_addr; // offset 16: address in virtual memory where this section may be loaded |
| 562 | uint64_t file_offset; // offset 24: offset of this section in the ELF file |
634 | uint64_t file_offset; // offset 24: offset of this section in the ELF file |
| 563 | uint64_t size; // offset 32: size of this section |
635 | uint64_t size; // offset 32: size of this section |
| 564 | uint32_t linked_index; // offset 40: optional section index of an associated section |
636 | uint32_t linked_index; // offset 40: optional section index of an associated section |
| 565 | uint32_t info; // offset 44: optional extra information |
637 | uint32_t info; // offset 44: optional extra information |
| 566 | uint64_t alignment; // offset 48: required memory alignment (must be a power of 2) |
638 | uint64_t alignment; // offset 48: required memory alignment (must be a power of 2) |
| 567 | uint64_t entry_size; // offset 56: for table-like sections, size of an element in the table |
639 | uint64_t entry_size; // offset 56: for table-like sections, size of an element in the table |
| 568 | } elf64; // size == 64 |
640 | } elf64; // size == 64 |
| 569 | } u; |
641 | } u; |
| 570 | } elf_section_header_t; |
642 | } elf_section_header_t; |
| - | 643 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 571 | 644 | ||
| 572 | 645 | ||
| 573 | // Executable and Linkable Format dynamic section entry structure type definition |
646 | // Executable and Linkable Format dynamic section entry structure type definition |
| - | 647 | START_OF_PACKED_STRUCT () // we need byte-alignment for this struct |
|
| 574 | typedef |
648 | typedef PACKED (struct) elf_dynamic_section_entry_s |
| 575 | { |
649 | { |
| 576 |
|
650 | PACKED (union) |
| 577 | { |
651 | { |
| 578 |
|
652 | PACKED (struct) // size == 8 |
| 579 | { |
653 | { |
| 580 | int32_t tag; // dynamic entry type (one of ELF_DT_xxx #defines) |
654 | int32_t tag; // dynamic entry type (one of ELF_DT_xxx #defines) |
| 581 | union |
- | |
| 582 | { |
- | |
| 583 | uint32_t as_integer; // value as integer |
- | |
| 584 |
|
655 | uint32_t value; // value (as integer, or as pointed address) |
| 585 | } value; |
- | |
| 586 | } elf32; // size == 8 |
656 | } elf32; // size == 8 |
| 587 |
|
657 | PACKED (struct) // size == 16 |
| 588 | { |
658 | { |
| 589 | int64_t tag; // dynamic entry type (one of ELF_DT_xxx #defines) |
659 | int64_t tag; // dynamic entry type (one of ELF_DT_xxx #defines) |
| 590 | union |
- | |
| 591 | { |
- | |
| 592 | uint64_t as_integer; // value as intege |
- | |
| 593 |
|
660 | uint64_t value; // value (as integer, or as pointed address) |
| 594 | } value; |
- | |
| 595 | } elf64; // size == 16 |
661 | } elf64; // size == 16 |
| 596 | } u; |
662 | } u; |
| 597 | } elf_dynamic_section_entry_t; |
663 | } elf_dynamic_section_entry_t; |
| - | 664 | END_OF_PACKED_STRUCT () // restore default alignment |
|
| 598 | 665 | ||
| 599 | 666 | ||
| - | 667 | // generic buffer structure type definition |
|
| 600 |
|
668 | typedef struct buffer_s |
| - | 669 | { |
|
| 601 | |
670 | uint8_t *bytes; // mallocated data |
| - | 671 | size_t len; // length of allocated data |
|
| 602 |
|
672 | } buffer_t; |
| 603 | 673 | ||
| 604 | 674 | ||
| - | 675 | // IFS directory entry insertion parameters structure type definition |
|
| 605 | typedef struct parms_s |
676 | typedef struct parms_s |
| 606 | { |
677 | { |
| 607 | int dperms; // directory permissions (e.g. 0755) |
678 | int dperms; // directory permissions (e.g. 0755) |
| 608 | int perms; // file permissions (e.g. 0644) |
679 | int perms; // file permissions (e.g. 0644) |
| 609 | int uid; // owner user ID (e.g. 0 = root) |
680 | int uid; // owner user ID (e.g. 0 = root) |
| Line 616... | Line 687... | ||
| 616 | bool should_autosymlink_dylib; // dynamic libraries should be written under their official SONAME and a named symlink be created pointing at them |
687 | bool should_autosymlink_dylib; // dynamic libraries should be written under their official SONAME and a named symlink be created pointing at them |
| 617 | bool is_compiled_bootscript; // entry has [+script] attribute |
688 | bool is_compiled_bootscript; // entry has [+script] attribute |
| 618 | int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx) |
689 | int extra_ino_flags; // bitmap of extra inode flags (IFS_INO_xxx) |
| 619 | char search[10 * MAXPATHLEN]; // binary search path (the default one will be constructed at startup) |
690 | char search[10 * MAXPATHLEN]; // binary search path (the default one will be constructed at startup) |
| 620 | 691 | ||
| 621 |
|
692 | buffer_t data; |
| 622 | size_t datalen; |
- | |
| 623 | } parms_t; |
693 | } parms_t; |
| 624 | 694 | ||
| 625 | 695 | ||
| 626 | // global variables |
696 | // global variables |
| 627 | static char line_buffer[4096]; // scrap buffer for the IFS build file parser |
697 | static char line_buffer[4096]; // scrap buffer for the IFS build file parser |
| Line 655... | Line 725... | ||
| 655 | static int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer |
725 | static int32_t update_checksum (const void *data, const size_t data_len, const bool is_foreign_endianness); // compute an IFS image or startup checksum to store in the trailer |
| 656 | static long long read_integer (const char *str); // reads an integer number for a string that may be specified in either hex, octal or decimal base, and may have an optional unit suffix (k, m, g, t) |
726 | static long long read_integer (const char *str); // reads an integer number for a string that may be specified in either hex, octal or decimal base, and may have an optional unit suffix (k, m, g, t) |
| 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) |
727 | 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) |
| 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 |
728 | 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 |
| 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 |
729 | 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 |
| 660 | static char *read_filecontents (const char *pathname, const char *search_path, |
730 | static char *read_filecontents (const char *pathname, const char *search_path, buffer_t *outbuf); // 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) |
| 661 | static int fwrite_filecontents (const char *pathname, FILE *fp); // dumps the contents of pathname into fp |
731 | 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 |
732 | static int relative_offset_of_in (const char *name, const buffer_t *stringbuf); // 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 |
733 | 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 |
| 664 | static size_t fwrite_fsentry (const fsentry_t *fsentry, FILE *fp); // writes the given filesystem entry into fp (without its contents) |
734 | static size_t fwrite_fsentry (const fsentry_t *fsentry, FILE *fp); // writes the given filesystem entry into fp (without its contents) |
| 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 |
735 | 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 |
| 666 | static int fsentry_compare_pathnames_cb (const void *a, const void *b); // qsort() comparison callback that sorts filesystem entries by pathnames |
736 | static int fsentry_compare_pathnames_cb (const void *a, const void *b); // qsort() comparison callback that sorts filesystem entries by pathnames |
| 667 | static void update_MKIFS_PATH (const char *processor); |
737 | static void update_MKIFS_PATH (const char *processor); |
| Line 1020... | Line 1090... | ||
| 1020 | } |
1090 | } |
| 1021 | return (outstr); |
1091 | return (outstr); |
| 1022 | } |
1092 | } |
| 1023 | 1093 | ||
| 1024 | 1094 | ||
| 1025 | static char *read_filecontents (const char *pathname, const char *search_path, |
1095 | static char *read_filecontents (const char *pathname, const char *search_path, buffer_t *outbuf) |
| 1026 | { |
1096 | { |
| 1027 | // locates pathname among MKIFS_PATH, and places its contents in a buffer (caller frees). Returns resolved pathname (static buffer) or NULL. |
1097 | // locates pathname among MKIFS_PATH, and places its contents in a buffer (caller frees). Returns resolved pathname (static buffer) or NULL. |
| 1028 | 1098 | ||
| 1029 | static thread_local char final_pathname[MAXPATHLEN]; |
1099 | static thread_local char final_pathname[MAXPATHLEN]; |
| 1030 | 1100 | ||
| Line 1062... | Line 1132... | ||
| 1062 | fp = fopen (final_pathname, "rb"); |
1132 | fp = fopen (final_pathname, "rb"); |
| 1063 | if (fp == NULL) |
1133 | if (fp == NULL) |
| 1064 | return (NULL); // unexistent file (errno is set to ENOENT) |
1134 | return (NULL); // unexistent file (errno is set to ENOENT) |
| 1065 | 1135 | ||
| 1066 | fseek (fp, 0, SEEK_END); |
1136 | fseek (fp, 0, SEEK_END); |
| 1067 |
|
1137 | outbuf->len = ftell (fp); // measure file length |
| 1068 | fseek (fp, 0, SEEK_SET); |
1138 | fseek (fp, 0, SEEK_SET); |
| 1069 |
|
1139 | outbuf->bytes = malloc (outbuf->len); |
| 1070 | if ( |
1140 | if (outbuf->bytes == NULL) |
| 1071 | { |
1141 | { |
| 1072 | fclose (fp); |
1142 | fclose (fp); |
| 1073 |
|
1143 | outbuf->len = 0; |
| 1074 | return (NULL); // out of memory (errno is set to ENOMEM) |
1144 | return (NULL); // out of memory (errno is set to ENOMEM) |
| 1075 | } |
1145 | } |
| 1076 | if (fread ( |
1146 | if (fread (outbuf->bytes, 1, outbuf->len, fp) != outbuf->len) // read the file in whole |
| 1077 | { |
1147 | { |
| 1078 | fclose (fp); |
1148 | fclose (fp); |
| 1079 |
|
1149 | outbuf->len = 0; |
| 1080 | return (NULL); // short read (errno is set) |
1150 | return (NULL); // short read (errno is set) |
| 1081 | } |
1151 | } |
| 1082 | fclose (fp); // close the file |
1152 | fclose (fp); // close the file |
| 1083 | 1153 | ||
| 1084 | return (final_pathname); // file was read successfully and its content put in databuf with size datalen |
1154 | return (final_pathname); // file was read successfully and its content put in databuf with size datalen |
| Line 1115... | Line 1185... | ||
| 1115 | free (blob_buffer); |
1185 | free (blob_buffer); |
| 1116 | return (ret); |
1186 | return (ret); |
| 1117 | } |
1187 | } |
| 1118 | 1188 | ||
| 1119 | 1189 | ||
| 1120 | static int relative_offset_of_in (const char *name, const |
1190 | static int relative_offset_of_in (const char *name, const buffer_t *stringbuf) |
| 1121 | { |
1191 | { |
| 1122 | int name_len = (int) strlen (name) + 1; |
1192 | int name_len = (int) strlen (name) + 1; |
| 1123 | WELLMANNERED_ASSERT (name_len < |
1193 | WELLMANNERED_ASSERT (name_len < stringbuf->len, "bad call (name longer than string table)"); |
| 1124 | for (int idx = 0; idx <= |
1194 | for (int idx = 0; idx <= stringbuf->len - name_len; idx++) |
| 1125 | if (memcmp (& |
1195 | if (memcmp (&stringbuf->bytes[idx], name, name_len) == 0) |
| 1126 | return (idx); |
1196 | return (idx); |
| 1127 | WELLMANNERED_ASSERT (false, "bad call (name '%s' not found in string table)", name); |
1197 | WELLMANNERED_ASSERT (false, "bad call (name '%s' not found in string table)", name); |
| 1128 | return (0); |
1198 | return (0); |
| 1129 | } |
1199 | } |
| 1130 | 1200 | ||
| Line 1236... | Line 1306... | ||
| 1236 | } |
1306 | } |
| 1237 | 1307 | ||
| 1238 | 1308 | ||
| 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) |
1309 | static size_t add_fsentry (fsentry_t **fsentries, size_t *fsentry_count, parms_t *entry_parms, const char *stored_pathname, const char *buildhost_pathname) |
| 1240 | { |
1310 | { |
| 1241 | #define ADD_NAME_TO_STRINGTABLE( |
1311 | #define ADD_NAME_TO_STRINGTABLE(name,strtab) do { \ |
| 1242 | name_len = strlen ((name)) + 1; \ |
1312 | name_len = strlen ((name)) + 1; \ |
| 1243 | reallocated_ptr = realloc ( |
1313 | reallocated_ptr = realloc ((strtab).bytes, (strtab).len + name_len); \ |
| 1244 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); \ |
1314 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); \ |
| 1245 | |
1315 | (strtab).bytes = reallocated_ptr; \ |
| 1246 | memcpy (&( |
1316 | memcpy (&(strtab).bytes[(strtab).len], (name), name_len); \ |
| 1247 | |
1317 | (strtab).len += name_len; \ |
| - | 1318 | } while (0) |
|
| - | 1319 | #define APPEND_SECTION_DATA(section,sectionhdr_offset) do { \ |
|
| - | 1320 | memcpy (&entry_parms->data.bytes[entry_parms->data.len], (section).bytes, (section).len); /* write section in place */ \ |
|
| - | 1321 | free ((section).bytes); /* free it */ \ |
|
| - | 1322 | new_shdr = (elf_section_header_t *) &new_shtab.bytes[(sectionhdr_offset)]; /* now fix this section header */ \ |
|
| - | 1323 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, entry_parms->data.len); /* fix section offset in the new section headers table */ \ |
|
| - | 1324 | entry_parms->data.len += (section).len; /* update new ELF file length */ \ |
|
| 1248 | } while (0) |
1325 | } while (0) |
| 1249 | 1326 | ||
| 1250 | static thread_local char candidate_pathname[1024]; |
1327 | static thread_local char candidate_pathname[1024]; |
| 1251 | static int inode_count = 0; // will be preincremented each time this function is called |
1328 | static int inode_count = 0; // will be preincremented each time this function is called |
| 1252 | 1329 | ||
| Line 1264... | Line 1341... | ||
| 1264 | elf_program_header_t *phdr; |
1341 | elf_program_header_t *phdr; |
| 1265 | const char *canonical_dylib_name; |
1342 | const char *canonical_dylib_name; |
| 1266 | const char *dynamic_strings; // strings table of the ".dynamic" section |
1343 | const char *dynamic_strings; // strings table of the ".dynamic" section |
| 1267 | const char *last_dirsep; |
1344 | const char *last_dirsep; |
| 1268 | elf_header_t *elf; |
1345 | elf_header_t *elf; |
| 1269 | uint8_t *new_shdr_table = NULL; // mallocated |
- | |
| 1270 |
|
1346 | buffer_t new_shtab = { NULL, 0 }; |
| 1271 | uint8_t *elfsection_qnxinfo_data = NULL; // mallocated |
- | |
| 1272 |
|
1347 | buffer_t elfsection_qnxinfo = { NULL, 0 }; |
| 1273 | uint8_t *elfsection_qnxusage_data = NULL; // mallocated |
- | |
| 1274 |
|
1348 | buffer_t elfsection_qnxusage = { NULL, 0 }; |
| 1275 | uint8_t *elfsection_debuglink_data = NULL; // mallocated |
- | |
| 1276 |
|
1349 | buffer_t elfsection_debuglink = { NULL, 0 }; |
| 1277 | uint8_t *elfsection_buildid_data = NULL; // mallocated |
- | |
| 1278 |
|
1350 | buffer_t elfsection_buildid = { NULL, 0 }; |
| 1279 | uint8_t *elfsection_shstrtab_data = NULL; // mallocated |
- | |
| 1280 |
|
1351 | buffer_t elfsection_shstrtab = { NULL, 0 }; |
| 1281 | char *resolved_pathname; |
1352 | char *resolved_pathname; |
| 1282 | void *reallocated_ptr; |
1353 | void *reallocated_ptr; |
| 1283 | void *old_data; |
1354 | void *old_data; |
| 1284 | struct stat stat_buf; |
1355 | struct stat stat_buf; |
| 1285 | size_t new_shdrtable_offset; |
1356 | size_t new_shdrtable_offset; |
| Line 1307... | Line 1378... | ||
| 1307 | } |
1378 | } |
| 1308 | else if (entry_parms->is_compiled_bootscript) // else is it a startup script ? |
1379 | else if (entry_parms->is_compiled_bootscript) // else is it a startup script ? |
| 1309 | image_bootscript_ino = inode_count + 1; // save boot script inode number for image header |
1380 | image_bootscript_ino = inode_count + 1; // save boot script inode number for image header |
| 1310 | 1381 | ||
| 1311 | // do we already know the data for this data blob ? |
1382 | // do we already know the data for this data blob ? |
| 1312 | if (entry_parms->data != NULL) |
1383 | if (entry_parms->data.bytes != NULL) |
| 1313 | { |
1384 | { |
| 1314 | entry_parms->mtime = entry_parms->mtime_for_inline_files; |
1385 | entry_parms->mtime = entry_parms->mtime_for_inline_files; |
| 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-> |
1386 | 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->data.len); |
| 1316 | } |
1387 | } |
| 1317 | else if (buildhost_pathname != NULL) // else was a source file pathname supplied ? |
1388 | else if (buildhost_pathname != NULL) // else was a source file pathname supplied ? |
| 1318 | { |
1389 | { |
| 1319 | resolved_pathname = read_filecontents (buildhost_pathname, (entry_parms->search[0] != 0 ? entry_parms->search : MKIFS_PATH), &entry_parms->data |
1390 | resolved_pathname = read_filecontents (buildhost_pathname, (entry_parms->search[0] != 0 ? entry_parms->search : MKIFS_PATH), &entry_parms->data); // locate the file |
| 1320 | if (resolved_pathname == NULL) |
1391 | if (resolved_pathname == NULL) |
| 1321 | { |
1392 | { |
| 1322 | fprintf (stderr, "fatal error: filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: %s\n", buildhost_pathname, buildfile_pathname, lineno, strerror (errno)); |
1393 | fprintf (stderr, "fatal error: filesystem entry \"%s\" specified in \"%s\" line %d not found on build host: %s\n", buildhost_pathname, buildfile_pathname, lineno, strerror (errno)); |
| 1323 | exit (1); |
1394 | exit (1); |
| 1324 | } |
1395 | } |
| 1325 | stat (resolved_pathname, &stat_buf); // can't fail |
1396 | stat (resolved_pathname, &stat_buf); // can't fail |
| 1326 | if (entry_parms->mtime == UINT32_MAX) |
1397 | if (entry_parms->mtime == UINT32_MAX) |
| 1327 | entry_parms->mtime = (uint32_t) stat_buf.st_mtime; |
1398 | entry_parms->mtime = (uint32_t) stat_buf.st_mtime; |
| 1328 | fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" buildhost_file \"%s\" (len %zd)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, buildhost_pathname, entry_parms-> |
1399 | fprintf (stderr, "file: ino 0x%x uid %d gid %d mode 0%o path \"%s\" buildhost_file \"%s\" (len %zd)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, buildhost_pathname, entry_parms->data.len); |
| 1329 | } |
1400 | } |
| 1330 | 1401 | ||
| 1331 | // is the file we're storing an ELF file ? |
1402 | // is the file we're storing an ELF file ? |
| 1332 | if ((entry_parms-> |
1403 | if ((entry_parms->data.len > 52) // file is big enough to contain an ELF header |
| 1333 | && ((elf = (elf_header_t *) entry_parms->data) != NULL) // cast (necessary true) |
1404 | && ((elf = (elf_header_t *) entry_parms->data.bytes) != NULL) // cast (necessary true) |
| 1334 | && (memcmp (ELF_GET_STRING (elf, elf, magic), ELF_MAGIC_STR, 4) == 0)) // file starts with the ELF magic |
1405 | && (memcmp (ELF_GET_STRING (elf, elf, magic), ELF_MAGIC_STR, 4) == 0)) // file starts with the ELF magic |
| 1335 | { |
1406 | { |
| 1336 | // is the file we're storing a relocatable executable (i.e. a dynamic library) and should we check for its canonical name ? |
1407 | // is the file we're storing a relocatable executable (i.e. a dynamic library) and should we check for its canonical name ? |
| 1337 | if ((ELF_GET_NUMERIC (elf, elf, type) == 3) && entry_parms->should_autosymlink_dylib) |
1408 | if ((ELF_GET_NUMERIC (elf, elf, type) == 3) && entry_parms->should_autosymlink_dylib) |
| 1338 | { |
1409 | { |
| Line 1344... | Line 1415... | ||
| 1344 | shdr_dynstr = elf_get_section_header_by_name (elf, ".dynstr"); |
1415 | shdr_dynstr = elf_get_section_header_by_name (elf, ".dynstr"); |
| 1345 | 1416 | ||
| 1346 | // make sure we have both the dynamic section header and its own strings table header |
1417 | // make sure we have both the dynamic section header and its own strings table header |
| 1347 | if ((shdr_dynamic != NULL) && (shdr_dynstr != NULL)) |
1418 | if ((shdr_dynamic != NULL) && (shdr_dynstr != NULL)) |
| 1348 | { |
1419 | { |
| 1349 | dynamic_strings = (char *) &entry_parms->data[ELF_GET_NUMERIC (elf, shdr_dynstr, file_offset)]; // quick access to dynamic sections strings table |
1420 | dynamic_strings = (char *) &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr_dynstr, file_offset)]; // quick access to dynamic sections strings table |
| 1350 | 1421 | ||
| 1351 | // walk through the dynamic section, look for the DT_SONAME entry |
1422 | // walk through the dynamic section, look for the DT_SONAME entry |
| 1352 | for (dynamic_entry = (elf_dynamic_section_entry_t *) &entry_parms->data[ELF_GET_NUMERIC (elf, shdr_dynamic, file_offset)]; |
1423 | for (dynamic_entry = (elf_dynamic_section_entry_t *) &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr_dynamic, file_offset)]; |
| 1353 | (ELF_GET_NUMERIC (elf, dynamic_entry, tag) != ELF_DT_NULL); |
1424 | (ELF_GET_NUMERIC (elf, dynamic_entry, tag) != ELF_DT_NULL); |
| 1354 | dynamic_entry = (elf_dynamic_section_entry_t *) ((uint8_t *) dynamic_entry + ELF_STRUCT_SIZE (elf, dynamic_entry))) |
1425 | dynamic_entry = (elf_dynamic_section_entry_t *) ((uint8_t *) dynamic_entry + ELF_STRUCT_SIZE (elf, dynamic_entry))) |
| 1355 | if (ELF_GET_NUMERIC (elf, dynamic_entry, tag) == ELF_DT_SONAME) |
1426 | if (ELF_GET_NUMERIC (elf, dynamic_entry, tag) == ELF_DT_SONAME) |
| 1356 | { |
1427 | { |
| 1357 | canonical_dylib_name = dynamic_strings + ELF_GET_NUMERIC (elf, dynamic_entry, value |
1428 | canonical_dylib_name = dynamic_strings + ELF_GET_NUMERIC (elf, dynamic_entry, value); |
| 1358 | break; |
1429 | break; |
| 1359 | } |
1430 | } |
| 1360 | 1431 | ||
| 1361 | // do we have it ? |
1432 | // do we have it ? |
| 1362 | if ((canonical_dylib_name != NULL) && (canonical_dylib_name[0] != 0)) |
1433 | if ((canonical_dylib_name != NULL) && (canonical_dylib_name[0] != 0)) |
| Line 1375... | Line 1446... | ||
| 1375 | if (!(entry_parms->extra_ino_flags & IFS_INO_PROCESSED_ELF)) |
1446 | if (!(entry_parms->extra_ino_flags & IFS_INO_PROCESSED_ELF)) |
| 1376 | { |
1447 | { |
| 1377 | // NOTE: for each ELF file, mkifs |
1448 | // 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) |
1449 | // -> 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 |
1450 | // -> 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 |
1451 | // FIXME: what if a thrown away section is located between two program segments ? are they collapsed, moving the segments beyond it one slot down ? |
| 1381 | 1452 | ||
| 1382 | // reconstructed ELF: |
1453 | // reconstructed ELF: |
| 1383 | // ==== START OF FILE ==== |
1454 | // ==== START OF FILE ==== |
| 1384 | // ELF header |
1455 | // ELF header |
| 1385 | // program header table |
1456 | // program header table |
| 1386 | // (same sections, just p_addr offset |
1457 | // (same sections, just p_addr offset changed) |
| 1387 | // section data 5 (named ".note.gnu.build-id") |
1458 | // section data 5 (named ".note.gnu.build-id") |
| 1388 | // "............GNU....ZY.....c.o..l" |
1459 | // "............GNU....ZY.....c.o..l" |
| 1389 | // PROGRAM |
1460 | // PROGRAM |
| 1390 | // sections table |
1461 | // sections table |
| 1391 | // + section 1: ALL ZEROES |
1462 | // + section 1: ALL ZEROES |
| Line 1407... | Line 1478... | ||
| 1407 | // ".gnu_debuglink\0" |
1478 | // ".gnu_debuglink\0" |
| 1408 | // "QNX_usage\0" |
1479 | // "QNX_usage\0" |
| 1409 | // ".note.gnu.build-id\0" |
1480 | // ".note.gnu.build-id\0" |
| 1410 | // ==== END OF FILE ==== |
1481 | // ==== END OF FILE ==== |
| 1411 | 1482 | ||
| 1412 | // |
1483 | // parse the program header table, and measure the farthest offset known by this table where we'll write the reconstructed section headers table |
| 1413 | 1484 | ||
| 1414 | //first_offset = SIZE_MAX; |
- | |
| 1415 | new_shdrtable_offset = 0; |
1485 | new_shdrtable_offset = 0; |
| 1416 | table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); |
1486 | table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); |
| 1417 | for (table_index = 0; table_index < table_count; table_index++) |
1487 | for (table_index = 0; table_index < table_count; table_index++) |
| 1418 | { |
1488 | { |
| 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 |
1489 | phdr = (elf_program_header_t *) &entry_parms->data.bytes[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) |
1490 | 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); |
1491 | 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 | } |
1492 | } |
| 1426 | 1493 | ||
| 1427 | // |
1494 | // re-create the section header table |
| 1428 | 1495 | ||
| 1429 |
|
1496 | elfsection_shstrtab.bytes = malloc (1); // initialize an empty section headers strings table |
| 1430 | WELLMANNERED_ASSERT ( |
1497 | WELLMANNERED_ASSERT (elfsection_shstrtab.bytes, "out of memory"); |
| 1431 |
|
1498 | elfsection_shstrtab.bytes[0] = 0; |
| 1432 |
|
1499 | elfsection_shstrtab.len = 1; |
| 1433 | ADD_NAME_TO_STRINGTABLE (".shstrtab", |
1500 | ADD_NAME_TO_STRINGTABLE (".shstrtab", elfsection_shstrtab); |
| 1434 | 1501 | ||
| 1435 |
|
1502 | new_shtab.bytes = malloc (ELF_STRUCT_SIZE (elf, shdr)); // prepare a section headers table with just the default entry |
| 1436 | WELLMANNERED_ASSERT ( |
1503 | WELLMANNERED_ASSERT (new_shtab.bytes, "out of memory"); |
| 1437 | new_shdr_table = reallocated_ptr; // reallocation succeeded, save the new pointer |
- | |
| 1438 | memset ( |
1504 | memset (new_shtab.bytes, 0, ELF_STRUCT_SIZE (elf, shdr)); // the first section header is always zerofilled |
| 1439 |
|
1505 | new_shtab.len = ELF_STRUCT_SIZE (elf, shdr); // and remember how big the section headers table is now |
| 1440 | if ((shdr = elf_get_section_header_by_name (elf, "QNX_info")) != NULL) |
1506 | if ((shdr = elf_get_section_header_by_name (elf, "QNX_info")) != NULL) |
| 1441 | { |
1507 | { |
| 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 |
1508 | 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 | { |
1509 | { |
| 1444 |
|
1510 | elfsection_qnxinfo.len = ELF_GET_NUMERIC (elf, shdr, size); |
| 1445 |
|
1511 | elfsection_qnxinfo.bytes = malloc (elfsection_qnxinfo.len); |
| 1446 | WELLMANNERED_ASSERT ( |
1512 | WELLMANNERED_ASSERT (elfsection_qnxinfo.bytes, "out of memory"); |
| 1447 | memcpy ( |
1513 | memcpy (elfsection_qnxinfo.bytes, &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_qnxinfo.len); |
| 1448 | } |
1514 | } |
| 1449 | reallocated_ptr = realloc ( |
1515 | reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
| 1450 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
1516 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
| 1451 |
|
1517 | new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer |
| 1452 | new_qnxinfo_shdr_offset = |
1518 | new_qnxinfo_shdr_offset = new_shtab.len; // remember the new offset of this section header |
| 1453 |
|
1519 | new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
| 1454 | 1520 | ||
| 1455 | new_shdr = (elf_section_header_t *) & |
1521 | new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_qnxinfo_shdr_offset]; // now populate this section header |
| 1456 | ADD_NAME_TO_STRINGTABLE ("QNX_info", |
1522 | ADD_NAME_TO_STRINGTABLE ("QNX_info", elfsection_shstrtab); |
| 1457 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_info", |
1523 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_info", &elfsection_shstrtab)); // 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 |
1524 | 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 |
1525 | 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 |
1526 | 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 |
1527 | 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 |
1528 | ELF_SET_NUMERIC (elf, new_shdr, size, ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size |
| Line 1467... | Line 1533... | ||
| 1467 | } |
1533 | } |
| 1468 | if ((shdr = elf_get_section_header_by_name (elf, ".gnu_debuglink")) != NULL) |
1534 | if ((shdr = elf_get_section_header_by_name (elf, ".gnu_debuglink")) != NULL) |
| 1469 | { |
1535 | { |
| 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 |
1536 | 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 | { |
1537 | { |
| 1472 |
|
1538 | elfsection_debuglink.len = ELF_GET_NUMERIC (elf, shdr, size); |
| 1473 |
|
1539 | elfsection_debuglink.bytes = malloc (elfsection_debuglink.len); |
| 1474 | WELLMANNERED_ASSERT ( |
1540 | WELLMANNERED_ASSERT (elfsection_debuglink.bytes, "out of memory"); |
| 1475 | memcpy ( |
1541 | memcpy (elfsection_debuglink.bytes, &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_debuglink.len); |
| 1476 | } |
1542 | } |
| 1477 | reallocated_ptr = realloc ( |
1543 | reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
| 1478 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
1544 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
| 1479 |
|
1545 | new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer |
| 1480 | new_debuglink_shdr_offset = |
1546 | new_debuglink_shdr_offset = new_shtab.len; // remember the new offset of this section header |
| 1481 |
|
1547 | new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
| 1482 | 1548 | ||
| 1483 | new_shdr = (elf_section_header_t *) & |
1549 | new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_debuglink_shdr_offset]; // now populate this section header |
| 1484 | ADD_NAME_TO_STRINGTABLE (".gnu_debuglink", |
1550 | ADD_NAME_TO_STRINGTABLE (".gnu_debuglink", elfsection_shstrtab); |
| 1485 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".gnu_debuglink", |
1551 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".gnu_debuglink", &elfsection_shstrtab)); // 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 |
1552 | 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 |
1553 | 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 |
1554 | 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 |
1555 | 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 |
1556 | ELF_SET_NUMERIC (elf, new_shdr, size, ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size |
| Line 1495... | Line 1561... | ||
| 1495 | } |
1561 | } |
| 1496 | if ((shdr = elf_get_section_header_by_name (elf, "QNX_usage")) != NULL) |
1562 | if ((shdr = elf_get_section_header_by_name (elf, "QNX_usage")) != NULL) |
| 1497 | { |
1563 | { |
| 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 |
1564 | 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 | { |
1565 | { |
| 1500 |
|
1566 | elfsection_qnxusage.len = ELF_GET_NUMERIC (elf, shdr, size); |
| 1501 |
|
1567 | elfsection_qnxusage.bytes = malloc (elfsection_qnxusage.len); |
| 1502 | WELLMANNERED_ASSERT ( |
1568 | WELLMANNERED_ASSERT (elfsection_qnxusage.bytes, "out of memory"); |
| 1503 | memcpy ( |
1569 | memcpy (elfsection_qnxusage.bytes, &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_qnxusage.len); |
| 1504 | } |
1570 | } |
| 1505 | reallocated_ptr = realloc ( |
1571 | reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
| 1506 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
1572 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
| 1507 |
|
1573 | new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer |
| 1508 | new_qnxusage_shdr_offset = |
1574 | new_qnxusage_shdr_offset = new_shtab.len; // remember the new offset of this section header |
| 1509 |
|
1575 | new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
| 1510 | 1576 | ||
| 1511 | new_shdr = (elf_section_header_t *) & |
1577 | new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_qnxusage_shdr_offset]; // now populate this section header |
| 1512 | ADD_NAME_TO_STRINGTABLE ("QNX_usage", |
1578 | ADD_NAME_TO_STRINGTABLE ("QNX_usage", elfsection_shstrtab); |
| 1513 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_usage", |
1579 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in ("QNX_usage", &elfsection_shstrtab)); // 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 |
1580 | 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 |
1581 | 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 |
1582 | 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 |
1583 | 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 |
1584 | ELF_SET_NUMERIC (elf, new_shdr, size, ELF_GET_NUMERIC (elf, shdr, size)); // duplicate section size |
| Line 1523... | Line 1589... | ||
| 1523 | } |
1589 | } |
| 1524 | if ((shdr = elf_get_section_header_by_name (elf, ".note.gnu.build-id")) != NULL) |
1590 | if ((shdr = elf_get_section_header_by_name (elf, ".note.gnu.build-id")) != NULL) |
| 1525 | { |
1591 | { |
| 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 |
1592 | 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 | { |
1593 | { |
| 1528 |
|
1594 | elfsection_buildid.len = ELF_GET_NUMERIC (elf, shdr, size); |
| 1529 |
|
1595 | elfsection_buildid.bytes = malloc (elfsection_buildid.len); |
| 1530 | WELLMANNERED_ASSERT ( |
1596 | WELLMANNERED_ASSERT (elfsection_buildid.bytes, "out of memory"); |
| 1531 | memcpy ( |
1597 | memcpy (elfsection_buildid.bytes, &entry_parms->data.bytes[ELF_GET_NUMERIC (elf, shdr, file_offset)], elfsection_buildid.len); |
| 1532 | } |
1598 | } |
| 1533 | reallocated_ptr = realloc ( |
1599 | reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
| 1534 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
1600 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
| 1535 |
|
1601 | new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer |
| 1536 | new_buildid_shdr_offset = |
1602 | new_buildid_shdr_offset = new_shtab.len; // remember the new offset of this section header |
| 1537 |
|
1603 | new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
| 1538 | 1604 | ||
| 1539 | new_shdr = (elf_section_header_t *) & |
1605 | new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_buildid_shdr_offset]; // now populate this section header |
| 1540 | ADD_NAME_TO_STRINGTABLE (".note.gnu.build-id", |
1606 | ADD_NAME_TO_STRINGTABLE (".note.gnu.build-id", elfsection_shstrtab); |
| 1541 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".note.gnu.build-id", |
1607 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".note.gnu.build-id", &elfsection_shstrtab)); // 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 |
1608 | 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 |
1609 | 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 |
1610 | 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 |
1611 | 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 |
1612 | 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!) |
1613 | 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 |
1614 | 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 |
1615 | 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 |
1616 | ELF_SET_NUMERIC (elf, new_shdr, entry_size, ELF_GET_NUMERIC (elf, shdr, entry_size)); // duplicate section entry size |
| 1551 | } |
1617 | } |
| 1552 | reallocated_ptr = realloc ( |
1618 | reallocated_ptr = realloc (new_shtab.bytes, new_shtab.len + ELF_STRUCT_SIZE (elf, shdr)); // grow our section headers table to have one entry more |
| 1553 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
1619 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
| 1554 |
|
1620 | new_shtab.bytes = reallocated_ptr; // reallocation succeeded, save the new pointer |
| 1555 | new_shstrtab_shdr_offset = |
1621 | new_shstrtab_shdr_offset = new_shtab.len; // remember the new offset of this section header |
| 1556 |
|
1622 | new_shtab.len += ELF_STRUCT_SIZE (elf, shdr); // and remember how bigger the section headers table is now |
| 1557 | 1623 | ||
| 1558 | new_shdr = (elf_section_header_t *) & |
1624 | new_shdr = (elf_section_header_t *) &new_shtab.bytes[new_shstrtab_shdr_offset]; // now populate this section header |
| 1559 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".shstrtab", |
1625 | ELF_SET_NUMERIC (elf, new_shdr, name_offset, relative_offset_of_in (".shstrtab", &elfsection_shstrtab)); // update the relative offset of the section name |
| 1560 | ELF_SET_NUMERIC (elf, new_shdr, type, ELF_SECTIONTYPE_STRINGTABLE); // section type (SHT_STRTAB) |
1626 | 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) |
1627 | 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 |
1628 | 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); // |
1629 | ELF_SET_NUMERIC (elf, new_shdr, file_offset, WILL_BE_FILLED_LATER); // will be filled once we know it |
| 1564 | ELF_SET_NUMERIC (elf, new_shdr, size, |
1630 | ELF_SET_NUMERIC (elf, new_shdr, size, elfsection_shstrtab.len); // section size |
| 1565 | ELF_SET_NUMERIC (elf, new_shdr, linked_index, 0); // this section is not linked to any other |
1631 | 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 |
1632 | 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 |
1633 | 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 |
1634 | ELF_SET_NUMERIC (elf, new_shdr, entry_size, 0); // this section is not a table, so entry_size is zero |
| 1569 | 1635 | ||
| 1570 | // jump over the new section headers table and write the sections that need to be relocated after the section headers table |
1636 | // jump over the new section headers table and write the sections that need to be relocated after the section headers table |
| 1571 | entry_parms-> |
1637 | entry_parms->data.len = new_shdrtable_offset + new_shtab.len; // assume there are no sections beyond the section headers table until known otherwise |
| 1572 | if ( |
1638 | if (elfsection_qnxinfo.bytes != 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 |
|
1639 | APPEND_SECTION_DATA (elfsection_qnxinfo, new_qnxinfo_shdr_offset); // write "QNX_info" section data if we have such a section |
| 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 ( |
1640 | if (elfsection_debuglink.bytes != 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 |
|
1641 | APPEND_SECTION_DATA (elfsection_debuglink, new_debuglink_shdr_offset); // write ".gnu_debuglink" section data if we have such a section |
| 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 ( |
1642 | if (elfsection_qnxusage.bytes != 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 |
|
1643 | APPEND_SECTION_DATA (elfsection_qnxusage, new_qnxusage_shdr_offset); // write "QNX_usage" section data if we have such a section |
| 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 ( |
1644 | if (elfsection_buildid.bytes != 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 |
|
1645 | APPEND_SECTION_DATA (elfsection_buildid, new_buildid_shdr_offset); // write ".note.gnu.build-id" section data if we have such a section |
| 1602 | entry_parms->datalen += elfsection_buildid_size; // update new ELF file length |
- | |
| 1603 | } |
- | |
| 1604 | if (elfsection_shstrtab_data != NULL) |
- | |
| 1605 | { |
- | |
| 1606 |
|
1646 | APPEND_SECTION_DATA (elfsection_shstrtab, new_shstrtab_shdr_offset); // write the section header strings table as the last section |
| 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 | 1647 | ||
| 1613 | // now write the section headers table |
1648 | // 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], |
1649 | memcpy (&entry_parms->data.bytes[new_shdrtable_offset], new_shtab.bytes, new_shtab.len); |
| 1616 | free ( |
1650 | free (new_shtab.bytes); // free it |
| 1617 | 1651 | ||
| 1618 | // and finally fix the ELF header |
1652 | // and finally fix the ELF header |
| 1619 | ELF_SET_NUMERIC (elf, elf, section_header_table_offset, new_shdrtable_offset); |
1653 | ELF_SET_NUMERIC (elf, elf, section_header_table_offset, new_shdrtable_offset); |
| 1620 | ELF_SET_NUMERIC (elf, elf, section_header_table_len, |
1654 | ELF_SET_NUMERIC (elf, elf, section_header_table_len, new_shtab.len / ELF_STRUCT_SIZE (elf, shdr)); |
| 1621 | ELF_SET_NUMERIC (elf, elf, section_header_names_idx, |
1655 | ELF_SET_NUMERIC (elf, elf, section_header_names_idx, new_shtab.len / ELF_STRUCT_SIZE (elf, shdr) - 1); // the section headers strings table is the last section |
| 1622 | 1656 | ||
| 1623 | // align size with page size (4096 on x86, 16k on ARM) |
1657 | // align size with page size (4096 on x86, 16k on ARM) |
| 1624 | end_padding_offset = entry_parms-> |
1658 | end_padding_offset = entry_parms->data.len; |
| 1625 | if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_X86_64) |
1659 | if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_X86_64) |
| 1626 | entry_parms-> |
1660 | entry_parms->data.len = 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) |
1661 | else if (ELF_GET_NUMERIC (elf, elf, instruction_set) == ELF_MACHINE_AARCH64) |
| 1628 | entry_parms-> |
1662 | entry_parms->data.len = ROUND_TO_UPPER_MULTIPLE (end_padding_offset, 16 * 1024); // 16 kb pages on ARM64 |
| 1629 | else |
1663 | else |
| 1630 | { |
1664 | { |
| 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); |
1665 | 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); |
1666 | exit (1); |
| 1633 | } |
1667 | } |
| 1634 | memset (&entry_parms->data[end_padding_offset], 0, entry_parms-> |
1668 | memset (&entry_parms->data.bytes[end_padding_offset], 0, entry_parms->data.len - end_padding_offset); // zerofill |
| 1635 | 1669 | ||
| 1636 | entry_parms->extra_ino_flags |= IFS_INO_PROCESSED_ELF; // mark this inode as a preprocessed ELF file |
1670 | 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 |
1671 | } // end if the file is not yet a processed ELF |
| 1638 | } // end if the file we're storing is an ELF file |
1672 | } // end if the file we're storing is an ELF file |
| 1639 | } |
1673 | } |
| 1640 | else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ? |
1674 | else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ? |
| 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); |
1675 | 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.bytes); |
| 1642 | else // we must be storing a FIFO |
1676 | else // we must be storing a FIFO |
| 1643 | { |
1677 | { |
| 1644 | if (strchr (entry_parms->data, ':') == NULL) |
1678 | if (strchr (entry_parms->data.bytes, ':') == NULL) |
| 1645 | { |
1679 | { |
| 1646 | fprintf (stderr, "fatal error: device entry \"%s\" malformed (no 'dev:rdev' pair)\n", stored_pathname); |
1680 | fprintf (stderr, "fatal error: device entry \"%s\" malformed (no 'dev:rdev' pair)\n", stored_pathname); |
| 1647 | exit (1); |
1681 | exit (1); |
| 1648 | } |
1682 | } |
| 1649 | fprintf (stderr, "fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev rdev %s)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data); |
1683 | fprintf (stderr, "fifo: ino 0x%x uid %d gid %d mode 0%o path \"%s\" dev rdev %s)\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data.bytes); |
| 1650 | } |
1684 | } |
| 1651 | 1685 | ||
| 1652 | // grow filesystem entries array to hold one more slot |
1686 | // grow filesystem entries array to hold one more slot |
| 1653 | reallocated_ptr = realloc (*fsentries, (*fsentry_count + 1) * sizeof (fsentry_t)); // attempt to reallocate |
1687 | reallocated_ptr = realloc (*fsentries, (*fsentry_count + 1) * sizeof (fsentry_t)); // attempt to reallocate |
| 1654 | if (reallocated_ptr == NULL) |
1688 | if (reallocated_ptr == NULL) |
| Line 1672... | Line 1706... | ||
| 1672 | fsentry->UNSAVED_was_data_written = true; // no data to save |
1706 | fsentry->UNSAVED_was_data_written = true; // no data to save |
| 1673 | } |
1707 | } |
| 1674 | else if (S_ISREG (entry_parms->st_mode)) |
1708 | else if (S_ISREG (entry_parms->st_mode)) |
| 1675 | { |
1709 | { |
| 1676 | fsentry->u.file.offset = WILL_BE_FILLED_LATER; // will be filled later in main() when the file's data blob will be written to the output file |
1710 | fsentry->u.file.offset = WILL_BE_FILLED_LATER; // will be filled later in main() when the file's data blob will be written to the output file |
| 1677 | fsentry->u.file.size = (uint32_t) entry_parms-> |
1711 | fsentry->u.file.size = (uint32_t) entry_parms->data.len; |
| 1678 | fsentry->u.file.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname); |
1712 | fsentry->u.file.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname); |
| 1679 | fsentry->u.file.UNSAVED_databuf = malloc (entry_parms-> |
1713 | fsentry->u.file.UNSAVED_databuf = malloc (entry_parms->data.len); |
| 1680 | WELLMANNERED_ASSERT (fsentry->u.file.UNSAVED_databuf, "out of memory"); |
1714 | WELLMANNERED_ASSERT (fsentry->u.file.UNSAVED_databuf, "out of memory"); |
| 1681 | memcpy (fsentry->u.file.UNSAVED_databuf, entry_parms->data, entry_parms-> |
1715 | memcpy (fsentry->u.file.UNSAVED_databuf, entry_parms->data.bytes, entry_parms->data.len); |
| 1682 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.file.path) + 1, image_align); // now we can set the size |
1716 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.file.path) + 1, image_align); // now we can set the size |
| 1683 | fsentry->UNSAVED_was_data_written = false; // there *IS* data to save |
1717 | fsentry->UNSAVED_was_data_written = false; // there *IS* data to save |
| 1684 | } |
1718 | } |
| 1685 | else if (S_ISLNK (entry_parms->st_mode)) |
1719 | else if (S_ISLNK (entry_parms->st_mode)) |
| 1686 | { |
1720 | { |
| 1687 | fsentry->u.symlink.sym_offset = (uint16_t) (strlen (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname) + 1); |
1721 | fsentry->u.symlink.sym_offset = (uint16_t) (strlen (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname) + 1); |
| 1688 | fsentry->u.symlink.sym_size = (uint16_t) entry_parms-> |
1722 | fsentry->u.symlink.sym_size = (uint16_t) entry_parms->data.len; |
| 1689 | fsentry->u.symlink.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname); |
1723 | fsentry->u.symlink.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname); |
| 1690 | fsentry->u.symlink.contents = strdup (entry_parms->data); |
1724 | fsentry->u.symlink.contents = strdup (entry_parms->data.bytes); |
| 1691 | WELLMANNERED_ASSERT (fsentry->u.symlink.contents, "out of memory"); |
1725 | WELLMANNERED_ASSERT (fsentry->u.symlink.contents, "out of memory"); |
| 1692 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint16_t) + sizeof (uint16_t) + (size_t) fsentry->u.symlink.sym_offset + fsentry->u.symlink.sym_size + 1, image_align); // now we can set the size |
1726 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint16_t) + sizeof (uint16_t) + (size_t) fsentry->u.symlink.sym_offset + fsentry->u.symlink.sym_size + 1, image_align); // now we can set the size |
| 1693 | fsentry->UNSAVED_was_data_written = true; // no data to save |
1727 | fsentry->UNSAVED_was_data_written = true; // no data to save |
| 1694 | } |
1728 | } |
| 1695 | else // necessarily a device node |
1729 | else // necessarily a device node |
| 1696 | { |
1730 | { |
| 1697 | fsentry->u.device.dev = strtol (entry_parms->data, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers |
1731 | fsentry->u.device.dev = strtol (entry_parms->data.bytes, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers |
| 1698 | fsentry->u.device.rdev = strtol (strchr (entry_parms->data, ':') + 1, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers |
1732 | fsentry->u.device.rdev = strtol (strchr (entry_parms->data.bytes, ':') + 1, NULL, 0); // use strtol() to parse decimal (...), hexadecimal (0x...) and octal (0...) numbers |
| 1699 | fsentry->u.device.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname); |
1733 | fsentry->u.device.path = strdup (stored_pathname[0] == '/' ? &stored_pathname[1] : stored_pathname); |
| 1700 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.device.path), image_align); // now we can set the size |
1734 | fsentry->header.size = (uint16_t) ROUND_TO_UPPER_MULTIPLE (sizeof (fsentry->header) + sizeof (uint32_t) + sizeof (uint32_t) + strlen (fsentry->u.device.path), image_align); // now we can set the size |
| 1701 | fsentry->UNSAVED_was_data_written = true; // no data to save |
1735 | fsentry->UNSAVED_was_data_written = true; // no data to save |
| 1702 | } |
1736 | } |
| 1703 | (*fsentry_count)++; |
1737 | (*fsentry_count)++; |
| Line 1709... | Line 1743... | ||
| 1709 | entry_parms->should_autosymlink_dylib = false; |
1743 | entry_parms->should_autosymlink_dylib = false; |
| 1710 | entry_parms->should_follow_symlinks = false; |
1744 | entry_parms->should_follow_symlinks = false; |
| 1711 | entry_parms->st_mode = S_IFLNK | 0777; // NOTE: mkifs stores symlink permissions as rwxrwxrwx ! |
1745 | 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 |
1746 | 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 |
| 1713 | last_dirsep = strrchr (stored_pathname, '/'); |
1747 | last_dirsep = strrchr (stored_pathname, '/'); |
| 1714 | old_data = entry_parms->data; // backup previous data pointer |
1748 | old_data = entry_parms->data.bytes; // backup previous data pointer |
| 1715 | entry_parms->data = (uint8_t *) (last_dirsep == NULL ? stored_pathname : last_dirsep + 1); // store symlink target in dirent data |
1749 | entry_parms->data.bytes = (uint8_t *) (last_dirsep == NULL ? stored_pathname : last_dirsep + 1); // store symlink target in dirent data |
| 1716 | entry_parms-> |
1750 | entry_parms->data.len = strlen (entry_parms->data.bytes); |
| 1717 | add_fsentry (fsentries, fsentry_count, entry_parms, original_stored_pathname, NULL); |
1751 | add_fsentry (fsentries, fsentry_count, entry_parms, original_stored_pathname, NULL); |
| 1718 | entry_parms->data = old_data; // restore previous data pointer so that it can be freed normally |
1752 | entry_parms->data.bytes = old_data; // restore previous data pointer so that it can be freed normally |
| 1719 | } |
1753 | } |
| 1720 | 1754 | ||
| 1721 | return (*fsentry_count); |
1755 | return (*fsentry_count); |
| 1722 | } |
1756 | } |
| 1723 | 1757 | ||
| Line 1801... | Line 1835... | ||
| 1801 | .should_follow_symlinks = true, // [+|-followlink] |
1835 | .should_follow_symlinks = true, // [+|-followlink] |
| 1802 | .should_autosymlink_dylib = true, // [+|-autolink] |
1836 | .should_autosymlink_dylib = true, // [+|-autolink] |
| 1803 | .is_compiled_bootscript = false, // [+|-script] |
1837 | .is_compiled_bootscript = false, // [+|-script] |
| 1804 | .extra_ino_flags = 0, |
1838 | .extra_ino_flags = 0, |
| 1805 | .search = "", |
1839 | .search = "", |
| 1806 | .data = NULL, |
1840 | .data = { NULL, 0 } |
| 1807 | .datalen = 0 |
- | |
| 1808 | }; |
1841 | }; |
| 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) |
1842 | 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) |
| 1810 | 1843 | ||
| 1811 | // bootable IFS support |
1844 | // bootable IFS support |
| 1812 | char *bootfile_pathname = NULL; // HACK: pathname to bootcode binary blob file to put at the start of a bootable IFS |
1845 | char *bootfile_pathname = NULL; // HACK: pathname to bootcode binary blob file to put at the start of a bootable IFS |
| Line 1826... | Line 1859... | ||
| 1826 | struct stat stat_buf; |
1859 | struct stat stat_buf; |
| 1827 | size_t startuptrailer_offset; |
1860 | size_t startuptrailer_offset; |
| 1828 | size_t startupheader_offset; |
1861 | size_t startupheader_offset; |
| 1829 | size_t imagetrailer_offset; |
1862 | size_t imagetrailer_offset; |
| 1830 | size_t imageheader_offset; |
1863 | size_t imageheader_offset; |
| - | 1864 | size_t corrective_offset; |
|
| 1831 | size_t imgdir_offset; |
1865 | size_t imgdir_offset; |
| 1832 | size_t imgdir_size; |
1866 | size_t imgdir_size; |
| 1833 | size_t final_size; |
1867 | size_t final_size; |
| 1834 | size_t blob_size; |
- | |
| 1835 | size_t available_space; |
1868 | size_t available_space; |
| 1836 | size_t allocated_size; |
1869 | size_t allocated_size; |
| 1837 | size_t fsentry_index; |
1870 | size_t fsentry_index; |
| 1838 | size_t largest_index; |
1871 | size_t largest_index; |
| 1839 | size_t largest_size; |
1872 | size_t largest_size; |
| 1840 | size_t curr_offset; |
1873 | size_t curr_offset; |
| 1841 | size_t table_index; |
1874 | size_t table_index; |
| 1842 | size_t table_count; |
1875 | size_t table_count; |
| 1843 |
|
1876 | buffer_t blob; |
| 1844 | int32_t checksum; |
1877 | int32_t checksum; |
| 1845 | char *specifiedpathname_start; |
1878 | char *specifiedpathname_start; |
| 1846 | char *directiveblock_start; |
1879 | char *directiveblock_start; |
| 1847 | char *write_ptr; |
1880 | char *write_ptr; |
| 1848 | char *line_ptr; |
1881 | char *line_ptr; |
| Line 1851... | Line 1884... | ||
| 1851 | char *sep; |
1884 | char *sep; |
| 1852 | //char *ctx; |
1885 | //char *ctx; |
| 1853 | int arg_index; |
1886 | int arg_index; |
| 1854 | bool is_quoted_context = false; |
1887 | bool is_quoted_context = false; |
| 1855 | bool is_escaped_char = false; |
1888 | bool is_escaped_char = false; |
| 1856 | bool |
1889 | bool should_discard_inline_contents = false; |
| 1857 | bool want_info = false; |
1890 | bool want_info = false; |
| 1858 | bool want_everything = false; |
1891 | bool want_everything = false; |
| 1859 | bool want_help = false; |
1892 | bool want_help = false; |
| 1860 | bool is_foreign_endianness; |
1893 | bool is_foreign_endianness; |
| 1861 | int string_len; |
1894 | int string_len; |
| Line 1894... | Line 1927... | ||
| 1894 | } |
1927 | } |
| 1895 | else if (strcmp (argv[arg_index], "-n") == 0) |
1928 | else if (strcmp (argv[arg_index], "-n") == 0) |
| 1896 | default_parms.mtime_for_inline_files = 0; // inline files should have a mtime set to zero |
1929 | default_parms.mtime_for_inline_files = 0; // inline files should have a mtime set to zero |
| 1897 | else if (strcmp (argv[arg_index], "-nn") == 0) |
1930 | else if (strcmp (argv[arg_index], "-nn") == 0) |
| 1898 | { |
1931 | { |
| 1899 | default_parms.mtime = 0; // all files should have a mtime set to zero |
1932 | default_parms.mtime = 0; // *all* files should have a mtime set to zero |
| 1900 | default_parms.mtime_for_inline_files = 0; |
1933 | default_parms.mtime_for_inline_files = 0; |
| 1901 | } |
1934 | } |
| 1902 | else if (strcmp (argv[arg_index], "--info") == 0) |
1935 | else if (strcmp (argv[arg_index], "--info") == 0) |
| 1903 | want_info = true; |
1936 | want_info = true; |
| 1904 | else if (strcmp (argv[arg_index], "--everything") == 0) |
1937 | else if (strcmp (argv[arg_index], "--everything") == 0) |
| Line 1920... | Line 1953... | ||
| 1920 | fprintf (stderr, "error: missing parameters\n"); |
1953 | fprintf (stderr, "error: missing parameters\n"); |
| 1921 | fprintf ((want_help ? stdout : stderr), "usage:\n"); |
1954 | fprintf ((want_help ? stdout : stderr), "usage:\n"); |
| 1922 | fprintf ((want_help ? stdout : stderr), " ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kernelfile <pathname>@<fileoffs>] [-n[n]] <buildfile> <outfile>\n"); |
1955 | fprintf ((want_help ? stdout : stderr), " ifstool [--bootfile <pathname>] [--startupfile <pathname>@<EP_from_imgbase>] [--kernelfile <pathname>@<fileoffs>] [-n[n]] <buildfile> <outfile>\n"); |
| 1923 | fprintf ((want_help ? stdout : stderr), " ifstool --info [--everything] <ifs file>\n"); |
1956 | fprintf ((want_help ? stdout : stderr), " ifstool --info [--everything] <ifs file>\n"); |
| 1924 | fprintf ((want_help ? stdout : stderr), " ifstool --help\n"); |
1957 | fprintf ((want_help ? stdout : stderr), " ifstool --help\n"); |
| 1925 | fprintf ((want_help ? stdout : stderr), " |
1958 | fprintf ((want_help ? stdout : stderr), "NOTE: the compilation feature requires predigested boot, startup and kernel files produced by mkifs.\n"); |
| 1926 | exit (want_help ? 0 : 1); |
1959 | exit (want_help ? 0 : 1); |
| 1927 | } |
1960 | } |
| 1928 | 1961 | ||
| 1929 | // do we want info about a particular IFS ? if so, dump it |
1962 | // do we want info about a particular IFS ? if so, dump it |
| 1930 | if (want_info) |
1963 | if (want_info) |
| Line 1957... | Line 1990... | ||
| 1957 | // stack up filesystem entries |
1990 | // stack up filesystem entries |
| 1958 | memcpy (&entry_parms, &default_parms, sizeof (default_parms)); |
1991 | memcpy (&entry_parms, &default_parms, sizeof (default_parms)); |
| 1959 | entry_parms.st_mode = S_IFDIR | default_parms.dperms; |
1992 | entry_parms.st_mode = S_IFDIR | default_parms.dperms; |
| 1960 | add_fsentry (&fsentries, &fsentry_count, &entry_parms, "", NULL); // add the root dir first |
1993 | add_fsentry (&fsentries, &fsentry_count, &entry_parms, "", NULL); // add the root dir first |
| 1961 | 1994 | ||
| - | 1995 | // parse the IFS build file line per line |
|
| 1962 | while (fgets (line_buffer, sizeof (line_buffer), buildfile_fp) != NULL) |
1996 | while (fgets (line_buffer, sizeof (line_buffer), buildfile_fp) != NULL) |
| 1963 | { |
1997 | { |
| 1964 | if (current_line != NULL) |
1998 | if (current_line != NULL) |
| 1965 | free (current_line); |
1999 | free (current_line); |
| 1966 | current_line = strdup (line_buffer); |
2000 | current_line = strdup (line_buffer); |
| 1967 | WELLMANNERED_ASSERT (current_line, "out of memory"); |
2001 | WELLMANNERED_ASSERT (current_line, "out of memory"); |
| 1968 | lineno++; // keep track of current line number |
2002 | lineno++; // keep track of current line number |
| 1969 | //fprintf (stderr, "read buildfile line %d: {%s}\n", lineno, line_buffer); |
- | |
| 1970 | 2003 | ||
| 1971 | line_ptr = line_buffer; |
2004 | line_ptr = line_buffer; |
| 1972 | while ((*line_ptr != 0) && isspace (*line_ptr)) |
2005 | while ((*line_ptr != 0) && isspace (*line_ptr)) |
| 1973 | line_ptr++; // skip leading spaces |
2006 | line_ptr++; // skip leading spaces |
| 1974 | 2007 | ||
| Line 1981... | Line 2014... | ||
| 1981 | 2014 | ||
| 1982 | // reset entry values |
2015 | // reset entry values |
| 1983 | memcpy (&entry_parms, &default_parms, sizeof (default_parms)); |
2016 | memcpy (&entry_parms, &default_parms, sizeof (default_parms)); |
| 1984 | path_in_ifs[0] = 0; |
2017 | path_in_ifs[0] = 0; |
| 1985 | path_on_buildhost[0] = 0; |
2018 | path_on_buildhost[0] = 0; |
| 1986 |
|
2019 | should_discard_inline_contents = false; |
| 1987 | - | ||
| 1988 | //fprintf (stderr, "parsing buildfile line %d: [%s]\n", lineno, line_ptr); |
- | |
| 1989 | 2020 | ||
| 1990 | // does this line start with an attribute block ? |
2021 | // does this line start with an attribute block ? |
| 1991 | if (*line_ptr == '[') |
2022 | if (*line_ptr == '[') |
| 1992 | { |
2023 | { |
| 1993 | line_ptr++; // skip the leading square bracket |
2024 | line_ptr++; // skip the leading square bracket |
| Line 2049... | Line 2080... | ||
| 2049 | fprintf (stderr, "error: unable to stat the boot file \"%s\" specified in \"%s\" line %d: %s\n", bootfile_pathname, buildfile_pathname, lineno, strerror (errno)); |
2080 | fprintf (stderr, "error: unable to stat the boot file \"%s\" specified in \"%s\" line %d: %s\n", bootfile_pathname, buildfile_pathname, lineno, strerror (errno)); |
| 2050 | exit (1); |
2081 | exit (1); |
| 2051 | } |
2082 | } |
| 2052 | bootfile_size = stat_buf.st_size; // save preboot file size |
2083 | bootfile_size = stat_buf.st_size; // save preboot file size |
| 2053 | fprintf (stderr, "info: processor \"%s\" bootfile \"%s\"\n", image_processor, bootfile_pathname); |
2084 | fprintf (stderr, "info: processor \"%s\" bootfile \"%s\"\n", image_processor, bootfile_pathname); |
| - | 2085 | #if 1 |
|
| - | 2086 | // ###################################################################################################################################################################################################################################### |
|
| - | 2087 | // # FIXME: figure out how to re-create it: linker call involved |
|
| - | 2088 | // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0xffff800000001000 --no-relax ${QNX_TARGET}/x86_64/boot/sys/procnto-smp-instr -o procnto-smp-instr.sym.UNSTRIPPED |
|
| - | 2089 | // ###################################################################################################################################################################################################################################### |
|
| 2054 | if (read_filecontents (kernelfile_pathname, ".", &entry_parms.data |
2090 | if (read_filecontents (kernelfile_pathname, ".", &entry_parms.data) == NULL) |
| 2055 | { |
2091 | { |
| 2056 | fprintf (stderr, "fatal error: unable to read precompiled kernel file \"%s\" specified in --kernelfile argument\n", kernelfile_pathname); |
2092 | fprintf (stderr, "fatal error: unable to read precompiled kernel file \"%s\" specified in --kernelfile argument\n", kernelfile_pathname); |
| 2057 | exit (1); |
2093 | exit (1); |
| 2058 | } |
2094 | } |
| - | 2095 | #else // nonworking |
|
| - | 2096 | strcpy (path_on_buildhost, "procnto-smp-instr"); |
|
| - | 2097 | #endif // nonworking |
|
| - | 2098 | ||
| 2059 |
|
2099 | should_discard_inline_contents = true; // remember we already have data (so as to discard the inline block's contents) |
| 2060 | } |
2100 | } |
| 2061 | else if (strncmp (token, "mtime=", 6) == 0) { REACH_TOKEN_VALUE (); if (strcmp (value, "*") == 0) entry_parms.mtime = UINT32_MAX; else { |
2101 | else if (strncmp (token, "mtime=", 6) == 0) { REACH_TOKEN_VALUE (); if (strcmp (value, "*") == 0) entry_parms.mtime = UINT32_MAX; else { |
| 2062 | // value *must* be "YYYY-MM-DD-HH:MM:SS" by specification |
2102 | // value *must* be "YYYY-MM-DD-HH:MM:SS" by specification |
| 2063 | memset (&utc_time, 0, sizeof (utc_time)); |
2103 | memset (&utc_time, 0, sizeof (utc_time)); |
| 2064 | if (sscanf (value, "%u-%u-%u-%u:%u:%u", &utc_time.tm_year, &utc_time.tm_mon, &utc_time.tm_mday, &utc_time.tm_hour, &utc_time.tm_min, &utc_time.tm_sec) != 6) |
2104 | if (sscanf (value, "%u-%u-%u-%u:%u:%u", &utc_time.tm_year, &utc_time.tm_mon, &utc_time.tm_mday, &utc_time.tm_hour, &utc_time.tm_min, &utc_time.tm_sec) != 6) |
| Line 2070... | Line 2110... | ||
| 2070 | entry_parms.mtime = (uint32_t) mktime (&utc_time); |
2110 | entry_parms.mtime = (uint32_t) mktime (&utc_time); |
| 2071 | } |
2111 | } |
| 2072 | } |
2112 | } |
| 2073 | else if (strcmp (token, "+script") == 0) { |
2113 | else if (strcmp (token, "+script") == 0) { |
| 2074 | entry_parms.is_compiled_bootscript = true; |
2114 | entry_parms.is_compiled_bootscript = true; |
| 2075 | entry_parms.data = malloc (sizeof (INITIAL_STARTUP_SCRIPT) - 1); |
2115 | entry_parms.data.bytes = malloc (sizeof (INITIAL_STARTUP_SCRIPT) - 1); |
| 2076 | WELLMANNERED_ASSERT (entry_parms.data, "out of memory"); |
2116 | WELLMANNERED_ASSERT (entry_parms.data.bytes, "out of memory"); |
| 2077 | memcpy (entry_parms.data, INITIAL_STARTUP_SCRIPT, sizeof (INITIAL_STARTUP_SCRIPT) - 1); // FIXME: HACK until the script compiler is implemented |
2117 | memcpy (entry_parms.data.bytes, INITIAL_STARTUP_SCRIPT, sizeof (INITIAL_STARTUP_SCRIPT) - 1); // FIXME: HACK until the script compiler is implemented |
| 2078 | entry_parms. |
2118 | entry_parms.data.len = sizeof (INITIAL_STARTUP_SCRIPT) - 1; |
| 2079 |
|
2119 | should_discard_inline_contents = true; // remember we already have data (so as to discard the inline block's contents) |
| 2080 | } |
2120 | } |
| 2081 | else if (strcmp (token, "-script") == 0) entry_parms.is_compiled_bootscript = false; |
2121 | else if (strcmp (token, "-script") == 0) entry_parms.is_compiled_bootscript = false; |
| 2082 | else if (strcmp (token, "+followlink") == 0) entry_parms.should_follow_symlinks = true; |
2122 | else if (strcmp (token, "+followlink") == 0) entry_parms.should_follow_symlinks = true; |
| 2083 | else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks = false; |
2123 | else if (strcmp (token, "-followlink") == 0) entry_parms.should_follow_symlinks = false; |
| 2084 | else if (strcmp (token, "+autolink") == 0) entry_parms.should_autosymlink_dylib = true; |
2124 | else if (strcmp (token, "+autolink") == 0) entry_parms.should_autosymlink_dylib = true; |
| Line 2168... | Line 2208... | ||
| 2168 | } |
2208 | } |
| 2169 | 2209 | ||
| 2170 | // read the host system's path, it may be either a path or a contents definition. Is it a content definition ? |
2210 | // read the host system's path, it may be either a path or a contents definition. Is it a content definition ? |
| 2171 | if (*line_ptr == '{') |
2211 | if (*line_ptr == '{') |
| 2172 | { |
2212 | { |
| 2173 | path_on_buildhost[0] = 0; // this is an inline fine, which means it doesn't exist on the build host |
- | |
| 2174 | allocated_size = 0; |
2213 | allocated_size = 0; |
| 2175 | 2214 | ||
| 2176 | line_ptr++; // skip the leading content definition |
2215 | line_ptr++; // skip the leading content definition |
| 2177 | is_escaped_char = false; |
2216 | is_escaped_char = false; |
| 2178 | for (;;) |
2217 | for (;;) |
| Line 2188... | Line 2227... | ||
| 2188 | else if ((read_char == '}') && !is_escaped_char) |
2227 | else if ((read_char == '}') && !is_escaped_char) |
| 2189 | break; // found an unescaped closing bracked, stop parsing |
2228 | break; // found an unescaped closing bracked, stop parsing |
| 2190 | else |
2229 | else |
| 2191 | { |
2230 | { |
| 2192 | is_escaped_char = false; // any other char, meaning the next one will not be escaped |
2231 | is_escaped_char = false; // any other char, meaning the next one will not be escaped |
| 2193 | if (! |
2232 | if (!should_discard_inline_contents) // only store the contents if we do NOT know the data yet |
| 2194 | { |
2233 | { |
| 2195 | if (entry_parms. |
2234 | if (entry_parms.data.len == allocated_size) // reallocate in 4 kb blocks |
| 2196 | { |
2235 | { |
| 2197 | reallocated_ptr = realloc (entry_parms.data, allocated_size + 4096); |
2236 | reallocated_ptr = realloc (entry_parms.data.bytes, allocated_size + 4096); |
| 2198 | WELLMANNERED_ASSERT (reallocated_ptr, "out of memory"); |
2237 | WELLMANNERED_ASSERT (reallocated_ptr != NULL, "out of memory"); |
| 2199 | entry_parms.data = reallocated_ptr; |
2238 | entry_parms.data.bytes = reallocated_ptr; |
| 2200 | allocated_size += 4096; |
2239 | allocated_size += 4096; |
| 2201 | } |
2240 | } |
| 2202 | entry_parms.data[entry_parms. |
2241 | entry_parms.data.bytes[entry_parms.data.len++] = read_char; |
| 2203 | } |
2242 | } |
| 2204 | if (read_char == '\n') |
2243 | if (read_char == '\n') |
| 2205 | lineno++; // update line counter as we parse the inline content |
2244 | lineno++; // update line counter as we parse the inline content |
| 2206 | } |
2245 | } |
| 2207 | } // end for |
2246 | } // end for |
| 2208 | has_data_already = true; // remember we have data now |
- | |
| 2209 | } |
2247 | } |
| 2210 | else // not a content definition between { brackets }, must be either a pathname on the build host, or the target of a symlink |
2248 | else // not a content definition between { brackets }, must be either a pathname on the build host, or the target of a symlink |
| 2211 | { |
2249 | { |
| 2212 | is_quoted_context = (*line_ptr == '"'); |
2250 | is_quoted_context = (*line_ptr == '"'); |
| 2213 | if (is_quoted_context) |
2251 | if (is_quoted_context) |
| Line 2229... | Line 2267... | ||
| 2229 | if (is_quoted_context && (*line_ptr == '"')) |
2267 | if (is_quoted_context && (*line_ptr == '"')) |
| 2230 | line_ptr++; // skip a possible final quote |
2268 | line_ptr++; // skip a possible final quote |
| 2231 | 2269 | ||
| 2232 | if (S_ISLNK (entry_parms.st_mode)) // are we storing a symlink ? |
2270 | if (S_ISLNK (entry_parms.st_mode)) // are we storing a symlink ? |
| 2233 | { |
2271 | { |
| 2234 | entry_parms.data = strdup (specifiedpathname_start); // if so, store the symlink target as the dirent's blob data |
2272 | entry_parms.data.bytes = strdup (specifiedpathname_start); // if so, store the symlink target as the dirent's blob data |
| 2235 | WELLMANNERED_ASSERT (entry_parms.data, "out of memory"); |
2273 | WELLMANNERED_ASSERT (entry_parms.data.bytes != NULL, "out of memory"); |
| 2236 | entry_parms. |
2274 | entry_parms.data.len = strlen (specifiedpathname_start); |
| 2237 | has_data_already = true; // remember we have data now |
- | |
| 2238 | } |
2275 | } |
| 2239 | else // it's a build host filesystem path |
2276 | else // it's a build host filesystem path |
| 2240 | strcpy (path_on_buildhost, line_ptr); // the path on the build host is given after the equal sign |
2277 | strcpy (path_on_buildhost, line_ptr); // the path on the build host is given after the equal sign |
| 2241 | } |
2278 | } |
| 2242 | } |
2279 | } |
| Line 2263... | Line 2300... | ||
| 2263 | else // file or device node |
2300 | else // file or device node |
| 2264 | entry_parms.st_mode |= entry_parms.perms; |
2301 | entry_parms.st_mode |= entry_parms.perms; |
| 2265 | 2302 | ||
| 2266 | add_fsentry (&fsentries, &fsentry_count, &entry_parms, path_in_ifs, path_on_buildhost); // and add filesystem entry |
2303 | add_fsentry (&fsentries, &fsentry_count, &entry_parms, path_in_ifs, path_on_buildhost); // and add filesystem entry |
| 2267 | 2304 | ||
| 2268 | if (entry_parms.data != NULL) |
2305 | if (entry_parms.data.bytes != NULL) |
| 2269 | free (entry_parms.data); // if blob data was allocated, free it |
2306 | free (entry_parms.data.bytes); // if blob data was allocated, free it |
| 2270 | } |
2307 | } |
| 2271 | 2308 | ||
| 2272 | // write IFS file |
2309 | // write IFS file |
| 2273 | fp = fopen (ifs_pathname, "w+b"); |
2310 | fp = fopen (ifs_pathname, "w+b"); |
| 2274 | if (fp == NULL) |
2311 | if (fp == NULL) |
| Line 2279... | Line 2316... | ||
| 2279 | 2316 | ||
| 2280 | // do we have a startup file ? if so, this is a bootable image |
2317 | // do we have a startup file ? if so, this is a bootable image |
| 2281 | if (startupfile_pathname != NULL) |
2318 | if (startupfile_pathname != NULL) |
| 2282 | { |
2319 | { |
| 2283 | // write boot prefix |
2320 | // write boot prefix |
| - | 2321 | // ###################################################################################################################################################################################################################################### |
|
| - | 2322 | // # FIXME: figure out how to re-create it |
|
| - | 2323 | // ###################################################################################################################################################################################################################################### |
|
| 2284 | fwrite_filecontents (bootfile_pathname, fp); |
2324 | fwrite_filecontents (bootfile_pathname, fp); |
| 2285 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
2325 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
| 2286 | 2326 | ||
| 2287 | startupheader_offset = ftell (fp); // save startup header offset |
2327 | startupheader_offset = ftell (fp); // save startup header offset |
| 2288 | memset (&startup_header, 0, sizeof (startup_header)); // prepare startup header |
2328 | memset (&startup_header, 0, sizeof (startup_header)); // prepare startup header |
| Line 2309... | Line 2349... | ||
| 2309 | startup_header.preboot_size = (uint16_t) bootfile_size; // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file)) |
2349 | startup_header.preboot_size = (uint16_t) bootfile_size; // [I ] Size of loaded before header, here 0xf30 or 3888 bytes (size of "bios.boot" file)) |
| 2310 | fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header |
2350 | fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header |
| 2311 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
2351 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
| 2312 | 2352 | ||
| 2313 | // ###################################################################################################################################################################################################################################### |
2353 | // ###################################################################################################################################################################################################################################### |
| 2314 | // # FIXME: figure out how to re-create it: |
2354 | // # FIXME: figure out how to re-create it: |
| - | 2355 | // first: open "startup-x86" ELF file, |
|
| - | 2356 | // lookup section headers table (there is no program headers table in this one) |
|
| - | 2357 | // FIXME: figure out something in there where the result is 0x1401030 !!! |
|
| 2315 | // |
2358 | // then: call the linker: ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0x1401030 --no-relax ${QNX_TARGET}/x86_64/boot/sys/startup-x86 -o startup.bin.UNSTRIPPED |
| - | 2359 | // then: parse resulting ELF file, take all program segments and concatenate them --> this is the blob (FIXME: wrong?) |
|
| 2316 | // ###################################################################################################################################################################################################################################### |
2360 | // ###################################################################################################################################################################################################################################### |
| - | 2361 | #if 0 // nonworking |
|
| - | 2362 | { |
|
| - | 2363 | buffer_t startupfile; |
|
| - | 2364 | elf_section_header_t *shdr_text; |
|
| - | 2365 | size_t segment_len; |
|
| - | 2366 | FILE *control_fp = fopen ("startup.bin.MYSTRIPPED", "wb"); |
|
| - | 2367 | ||
| - | 2368 | if (read_filecontents ("startup.bin.UNSTRIPPED", MKIFS_PATH, &startupfile) == NULL) |
|
| - | 2369 | { |
|
| - | 2370 | fprintf (stderr, "fatal error: couldn't read startup-x86\n"); |
|
| - | 2371 | exit (1); |
|
| - | 2372 | } |
|
| - | 2373 | elf = (elf_header_t *) startupfile.bytes; // quick access to ELF header |
|
| - | 2374 | table_count = ELF_GET_NUMERIC (elf, elf, program_header_table_len); // get the number of program headers |
|
| - | 2375 | for (table_index = 0; table_index < table_count; table_index++) // cycle through program headers |
|
| - | 2376 | { |
|
| - | 2377 | phdr = (elf_program_header_t *) &startupfile.bytes[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 |
|
| - | 2378 | segment_len = ELF_GET_NUMERIC (elf, phdr, size_in_file); |
|
| - | 2379 | fwrite_or_die (&startupfile.bytes[ELF_GET_NUMERIC (elf, phdr, file_offset)], 1, segment_len, fp); // dump program segment |
|
| - | 2380 | fwrite_or_die (&startupfile.bytes[ELF_GET_NUMERIC (elf, phdr, file_offset)], 1, segment_len, control_fp); // dump program segment |
|
| - | 2381 | while (segment_len % 4096 > 0) |
|
| - | 2382 | { |
|
| - | 2383 | fputc (0, control_fp); |
|
| - | 2384 | segment_len++; |
|
| - | 2385 | } |
|
| - | 2386 | } |
|
| - | 2387 | ||
| - | 2388 | fclose (control_fp); |
|
| - | 2389 | free (startupfile.bytes); |
|
| - | 2390 | } |
|
| - | 2391 | #else // working |
|
| 2317 | fwrite_filecontents (startupfile_pathname, fp); // write startup code from blob file |
2392 | fwrite_filecontents (startupfile_pathname, fp); // write startup code from blob file |
| - | 2393 | #endif // working |
|
| 2318 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
2394 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
| 2319 | 2395 | ||
| 2320 | startuptrailer_offset = ftell (fp); // save startup trailer offset |
2396 | startuptrailer_offset = ftell (fp); // save startup trailer offset |
| 2321 | fwrite_or_die (&startup_trailer, 1, sizeof (startup_trailer), fp); // write startup trailer |
2397 | fwrite_or_die (&startup_trailer, 1, sizeof (startup_trailer), fp); // write startup trailer |
| 2322 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
2398 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
| Line 2383... | Line 2459... | ||
| 2383 | largest_index = fsentry_index; |
2459 | largest_index = fsentry_index; |
| 2384 | } |
2460 | } |
| 2385 | } |
2461 | } |
| 2386 | if (largest_size == 0) |
2462 | if (largest_size == 0) |
| 2387 | break; // found none ? if so, stop searching |
2463 | break; // found none ? if so, stop searching |
| - | 2464 | ||
| - | 2465 | fsentries[largest_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure |
|
| 2388 | 2466 | ||
| 2389 | // is the file we're storing a preprocessed ELF file ? |
2467 | // is the file we're storing a preprocessed ELF file ? |
| 2390 | if (fsentries[ |
2468 | if (fsentries[largest_index].header.ino & IFS_INO_PROCESSED_ELF) |
| 2391 | { |
2469 | { |
| 2392 | elf = (elf_header_t *) fsentries[ |
2470 | elf = (elf_header_t *) fsentries[largest_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 |
2471 | 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++) |
2472 | for (table_index = 0; table_index < table_count; table_index++) |
| 2395 | { |
2473 | { |
| 2396 | phdr = (elf_program_header_t *) &fsentries[ |
2474 | phdr = (elf_program_header_t *) &fsentries[largest_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 |
| - | 2475 | corrective_offset = ELF_GET_NUMERIC (elf, phdr, virtual_addr) - ELF_GET_NUMERIC (elf, phdr, file_offset); |
|
| - | 2476 | if (ELF_GET_NUMERIC (elf, phdr, size_in_memory) != 0) // only patch the physical address of segments that have an actual size in memory |
|
| 2397 | ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + |
2477 | ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + 0x1400000 + curr_offset - corrective_offset); // patch the physical address member of the program header table |
| 2398 | } |
2478 | } |
| 2399 | } |
2479 | } |
| 2400 | 2480 | ||
| 2401 | fsentries[largest_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure |
- | |
| 2402 | fwrite_or_die (fsentries[largest_index].u.file.UNSAVED_databuf, 1, fsentries[largest_index].u.file.size, fp); // write file data blob |
2481 | fwrite_or_die (fsentries[largest_index].u.file.UNSAVED_databuf, 1, fsentries[largest_index].u.file.size, fp); // write file data blob |
| 2403 | fsentries[largest_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
2482 | fsentries[largest_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
| 2404 | } |
2483 | } |
| 2405 | fprintf (stderr, "Current offset: 0x%zx\n", curr_offset); |
2484 | fprintf (stderr, "Current offset: 0x%zx\n", curr_offset); |
| 2406 | fprintf (stderr, "Kernel file offset: 0x%zx\n", kernelfile_offset); |
2485 | fprintf (stderr, "Kernel file offset: 0x%zx\n", kernelfile_offset); |
| Line 2410... | Line 2489... | ||
| 2410 | for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++) |
2489 | for (fsentry_index = 1; fsentry_index < fsentry_count; fsentry_index++) |
| 2411 | if (fsentries[fsentry_index].header.ino == image_kernel_ino) |
2490 | if (fsentries[fsentry_index].header.ino == image_kernel_ino) |
| 2412 | break; // locate the kernel directory entry (can't fail) |
2491 | break; // locate the kernel directory entry (can't fail) |
| 2413 | curr_offset = ftell (fp); // see where we are |
2492 | curr_offset = ftell (fp); // see where we are |
| 2414 | fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure |
2493 | fsentries[fsentry_index].u.file.offset = (uint32_t) (curr_offset - imageheader_offset); // save file data blob offset in file structure |
| 2415 | // ###################################################################################################################################################################################################################################### |
- | |
| 2416 | // # FIXME: figure out how to re-create it: linker call involved |
- | |
| 2417 | // # $ x86_64-pc-nto-qnx8.0.0-ld --sysroot=${QNX_TARGET}/x86_64/ -T${QNX_TARGET}/x86_64/lib/nto.link --section-start .text=0xffff800000001000 --no-relax ${QNX_TARGET}/x86_64/boot/sys/procnto-smp-instr -o procnto-smp-instr.sym.UNSTRIPPED |
- | |
| 2418 | // ###################################################################################################################################################################################################################################### |
- | |
| 2419 |
|
2494 | fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write kernel file data blob |
| 2420 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
2495 | PAD_OUTFILE_TO (ROUND_TO_UPPER_MULTIPLE (ftell (fp), image_align)); // pad as necessary |
| 2421 | fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
2496 | fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
| 2422 | } |
2497 | } |
| 2423 | 2498 | ||
| 2424 | // then write all the other files by increasing inode number: ELF files first |
2499 | // then write all the other files by increasing inode number: ELF files first |
| Line 2436... | Line 2511... | ||
| 2436 | elf = (elf_header_t *) fsentries[fsentry_index].u.file.UNSAVED_databuf; // quick access to ELF header |
2511 | 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 |
2512 | 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++) |
2513 | for (table_index = 0; table_index < table_count; table_index++) |
| 2439 | { |
2514 | { |
| 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 |
2515 | 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 |
| - | 2516 | corrective_offset = ELF_GET_NUMERIC (elf, phdr, virtual_addr) - ELF_GET_NUMERIC (elf, phdr, file_offset); |
|
| - | 2517 | if (ELF_GET_NUMERIC (elf, phdr, size_in_memory) != 0) // only patch the physical address of segments that have an actual size in memory |
|
| 2441 | ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + |
2518 | ELF_SET_NUMERIC (elf, phdr, physical_addr, ELF_GET_NUMERIC (elf, phdr, physical_addr) + 0x1400000 + curr_offset - corrective_offset); // patch the physical address member of the program header table |
| 2442 | } |
2519 | } |
| 2443 | } |
2520 | } |
| 2444 | 2521 | ||
| 2445 | fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob |
2522 | fwrite_or_die (fsentries[fsentry_index].u.file.UNSAVED_databuf, 1, fsentries[fsentry_index].u.file.size, fp); // write file data blob |
| 2446 | fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
2523 | fsentries[fsentry_index].UNSAVED_was_data_written = true; // and remember this file's data was written |
| Line 2477... | Line 2554... | ||
| 2477 | { |
2554 | { |
| 2478 | // rewrite startup header with final values |
2555 | // rewrite startup header with final values |
| 2479 | fseek_or_die (fp, startupheader_offset, SEEK_SET); |
2556 | fseek_or_die (fp, startupheader_offset, SEEK_SET); |
| 2480 | startup_header.startup_size = (uint32_t) (imageheader_offset - startupheader_offset); // size of startup header up to image header |
2557 | startup_header.startup_size = (uint32_t) (imageheader_offset - startupheader_offset); // size of startup header up to image header |
| 2481 | startup_header.imagefs_size = (uint32_t) (final_size - imageheader_offset); // size of uncompressed imagefs |
2558 | startup_header.imagefs_size = (uint32_t) (final_size - imageheader_offset); // size of uncompressed imagefs |
| 2482 | startup_header.ram_size = (uint32_t) final_size |
2559 | startup_header.ram_size = (uint32_t) (final_size - startupheader_offset); |
| 2483 | startup_header.stored_size = (uint32_t) final_size; |
2560 | startup_header.stored_size = (uint32_t) (final_size - startupheader_offset); |
| 2484 | fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header |
2561 | fwrite_or_die (&startup_header, 1, sizeof (startup_header), fp); // write startup header |
| 2485 | } |
2562 | } |
| 2486 | 2563 | ||
| 2487 | // rewrite image header with final values |
2564 | // rewrite image header with final values |
| 2488 | fseek_or_die (fp, imageheader_offset, SEEK_SET); |
2565 | fseek_or_die (fp, imageheader_offset, SEEK_SET); |
| Line 2499... | Line 2576... | ||
| 2499 | 2576 | ||
| 2500 | fclose (fp); // ensure everything is flushed |
2577 | fclose (fp); // ensure everything is flushed |
| 2501 | 2578 | ||
| 2502 | // ALL CHECKSUMS AT THE VERY END |
2579 | // ALL CHECKSUMS AT THE VERY END |
| 2503 | 2580 | ||
| 2504 | blob_data = NULL; |
- | |
| 2505 | read_filecontents (ifs_pathname, ".", & |
2581 | read_filecontents (ifs_pathname, ".", &blob); |
| 2506 | WELLMANNERED_ASSERT ( |
2582 | WELLMANNERED_ASSERT (blob.bytes != NULL, "failed to open IFS file for checksumming: %s", strerror (errno)); |
| 2507 | 2583 | ||
| 2508 | // do we have a startup file ? if so, this is a bootable image |
2584 | // do we have a startup file ? if so, this is a bootable image |
| 2509 | if (startupfile_pathname != NULL) |
2585 | if (startupfile_pathname != NULL) |
| 2510 | { |
2586 | { |
| 2511 | // compute SHA-512 checksum and V1 checksum of startup block |
2587 | // compute SHA-512 checksum and V1 checksum of startup block |
| Line 2513... | Line 2589... | ||
| 2513 | || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) |
2589 | || (!(startup_header.flags1 & STARTUP_HDR_FLAGS1_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) |
| 2514 | is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness |
2590 | is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness |
| 2515 | else |
2591 | else |
| 2516 | is_foreign_endianness = false; // else this header is for the same endianness as us |
2592 | is_foreign_endianness = false; // else this header is for the same endianness as us |
| 2517 | 2593 | ||
| 2518 | SHA512 (& |
2594 | SHA512 (&blob.bytes[startupheader_offset], startuptrailer_offset - startupheader_offset, &blob.bytes[startuptrailer_offset]); // compute SHA512 checksum and write it in place in blob data |
| 2519 | checksum = update_checksum (& |
2595 | checksum = update_checksum (&blob.bytes[startupheader_offset], startuptrailer_offset + SHA512_DIGEST_LENGTH - startupheader_offset, is_foreign_endianness); // compute old checksum |
| 2520 | memcpy (& |
2596 | memcpy (&blob.bytes[startuptrailer_offset + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place |
| 2521 | } |
2597 | } |
| 2522 | 2598 | ||
| 2523 | // compute SHA-512 checksum and V1 checksum of image block |
2599 | // compute SHA-512 checksum and V1 checksum of image block |
| 2524 | if ( ( (image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) |
2600 | if ( ( (image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) |
| 2525 | || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) |
2601 | || (!(image_header.flags & IMAGE_FLAGS_BIGENDIAN) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__))) |
| 2526 | is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness |
2602 | is_foreign_endianness = true; // if the header is big endian and we're on a little endian machine, or the other way around, it's a foreign endianness |
| 2527 | else |
2603 | else |
| 2528 | is_foreign_endianness = false; // else this header is for the same endianness as us |
2604 | is_foreign_endianness = false; // else this header is for the same endianness as us |
| 2529 | 2605 | ||
| 2530 | SHA512 (& |
2606 | SHA512 (&blob.bytes[imageheader_offset], imagetrailer_offset - imageheader_offset, &blob.bytes[imagetrailer_offset]); // compute SHA512 checksum and write it in place in blob data |
| 2531 | checksum = update_checksum (& |
2607 | checksum = update_checksum (&blob.bytes[imageheader_offset], imagetrailer_offset + SHA512_DIGEST_LENGTH - imageheader_offset, is_foreign_endianness); // compute old checksum |
| 2532 | memcpy (& |
2608 | memcpy (&blob.bytes[imagetrailer_offset + SHA512_DIGEST_LENGTH], &checksum, 4); // and write it in place |
| 2533 | 2609 | ||
| 2534 | // now rewrite IFS with the correct checksums |
2610 | // now rewrite IFS with the correct checksums |
| 2535 | fp = fopen (ifs_pathname, "wb"); |
2611 | fp = fopen (ifs_pathname, "wb"); |
| 2536 | WELLMANNERED_ASSERT (fp, "failed to reopen IFS file for checksumming: %s", strerror (errno)); |
2612 | WELLMANNERED_ASSERT (fp, "failed to reopen IFS file for checksumming: %s", strerror (errno)); |
| 2537 | fwrite_or_die ( |
2613 | fwrite_or_die (blob.bytes, 1, blob.len, fp); |
| 2538 | fclose (fp); |
2614 | fclose (fp); |
| 2539 | free ( |
2615 | free (blob.bytes); |
| 2540 | 2616 | ||
| 2541 | // finished, exit with a success code |
2617 | // finished, exit with a success code |
| 2542 | fprintf (stdout, "Success\n"); |
2618 | fprintf (stdout, "Success\n"); |
| 2543 | exit (0); |
2619 | exit (0); |
| 2544 | } |
2620 | } |
| Line 2601... | Line 2677... | ||
| 2601 | size_t nearest_distance; |
2677 | size_t nearest_distance; |
| 2602 | size_t nearest_index; |
2678 | size_t nearest_index; |
| 2603 | size_t byte_index; |
2679 | size_t byte_index; |
| 2604 | uint32_t recorded_checksum; |
2680 | uint32_t recorded_checksum; |
| 2605 | uint32_t computed_checksum; |
2681 | uint32_t computed_checksum; |
| 2606 | uint8_t *filedata; |
- | |
| 2607 |
|
2682 | buffer_t file; |
| 2608 | time_t mtime; |
2683 | time_t mtime; |
| 2609 | 2684 | ||
| 2610 | // open and read IFS file |
2685 | // open and read IFS file |
| 2611 | if (read_filecontents (ifs_pathname, ".", & |
2686 | if (read_filecontents (ifs_pathname, ".", &file) == NULL) |
| 2612 | { |
2687 | { |
| 2613 | fprintf (stderr, "error: can't open \"%s\" for reading: %s\n", ifs_pathname, strerror (errno)); |
2688 | fprintf (stderr, "error: can't open \"%s\" for reading: %s\n", ifs_pathname, strerror (errno)); |
| 2614 | return (1); |
2689 | return (1); |
| 2615 | } |
2690 | } |
| 2616 | 2691 | ||
| 2617 | printf ("QNX In-kernel Filesystem analysis produced by ifstool version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD); |
2692 | printf ("QNX In-kernel Filesystem analysis produced by ifstool version " VERSION_FMT_YYYYMMDD "\n", VERSION_ARG_YYYYMMDD); |
| 2618 | printf ("IFS file \"%s\" - size 0x%zx (%zd) bytes\n", ifs_pathname, |
2693 | printf ("IFS file \"%s\" - size 0x%zx (%zd) bytes\n", ifs_pathname, file.len, file.len); |
| 2619 | 2694 | ||
| 2620 | // parse file from start to end |
2695 | // parse file from start to end |
| 2621 | current_offset = 0; |
2696 | current_offset = 0; |
| 2622 | for (;;) |
2697 | for (;;) |
| 2623 | { |
2698 | { |
| 2624 | // does a startup header start here ? |
2699 | // does a startup header start here ? |
| 2625 | if ((current_offset + sizeof (startup_header_t) < |
2700 | if ((current_offset + sizeof (startup_header_t) < file.len) && (memcmp (&file.bytes[current_offset], "\xeb\x7e\xff\x00", 4) == 0)) |
| 2626 | { |
2701 | { |
| 2627 | startupheader_offset = current_offset; |
2702 | startupheader_offset = current_offset; |
| 2628 | startup_header = (startup_header_t *) & |
2703 | startup_header = (startup_header_t *) &file.bytes[startupheader_offset]; |
| 2629 | 2704 | ||
| 2630 | // layout: |
2705 | // layout: |
| 2631 | // [STARTUP HEADER] |
2706 | // [STARTUP HEADER] |
| 2632 | // (startup file blob) |
2707 | // (startup file blob) |
| 2633 | // [STARTUP TRAILER v1 or v2] |
2708 | // [STARTUP TRAILER v1 or v2] |
| Line 2643... | Line 2718... | ||
| 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); |
2718 | printf (" startup_vaddr = 0x%08x (%d) - virtual address to transfer to after IPL is done\n", startup_header->startup_vaddr, startup_header->startup_vaddr); |
| 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); |
2719 | 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); |
| 2645 | printf (" image_paddr = 0x%08x (%d) - physical address of image\n", startup_header->image_paddr, startup_header->image_paddr); |
2720 | printf (" image_paddr = 0x%08x (%d) - physical address of image\n", startup_header->image_paddr, startup_header->image_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); |
2721 | 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); |
| 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); |
2722 | 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); |
| 2648 | printf (" startup_size = 0x%08x (%d) - size of startup (never compressed) - %s\n", startup_header->startup_size, startup_header->startup_size, (current_offset + sizeof (image_header_t) + startup_header->startup_size + (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)) < |
2723 | printf (" startup_size = 0x%08x (%d) - size of startup (never compressed) - %s\n", startup_header->startup_size, startup_header->startup_size, (current_offset + sizeof (image_header_t) + startup_header->startup_size + (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)) < file.len ? "looks good" : "BAD (IFS file too short)")); |
| 2649 | printf (" stored_size = 0x%08x (%d) - size of entire image - %s\n", startup_header->stored_size, startup_header->stored_size, (startup_header->stored_size == startup_header->ram_size ? "looks good" : "???")); |
2724 | printf (" stored_size = 0x%08x (%d) - size of entire image - %s\n", startup_header->stored_size, startup_header->stored_size, (startup_header->stored_size == startup_header->ram_size ? "looks good" : "???")); |
| 2650 | printf (" imagefs_paddr = 0x%08x (%d) - set by IPL when startup runs - %s\n", startup_header->imagefs_paddr, startup_header->imagefs_paddr, (startup_header->imagefs_paddr == 0 ? "looks good" : "??? should be zero")); |
2725 | printf (" imagefs_paddr = 0x%08x (%d) - set by IPL when startup runs - %s\n", startup_header->imagefs_paddr, startup_header->imagefs_paddr, (startup_header->imagefs_paddr == 0 ? "looks good" : "??? should be zero")); |
| 2651 | printf (" imagefs_size = 0x%08x (%d) - size of uncompressed imagefs\n", startup_header->imagefs_size, startup_header->imagefs_size); |
2726 | printf (" imagefs_size = 0x%08x (%d) - size of uncompressed imagefs\n", startup_header->imagefs_size, startup_header->imagefs_size); |
| 2652 | printf (" preboot_size = 0x%04x (%d) - size of loaded before header - %s\n", startup_header->preboot_size, startup_header->preboot_size, (startup_header->preboot_size == current_offset ? "looks good" : "???")); |
2727 | printf (" preboot_size = 0x%04x (%d) - size of loaded before header - %s\n", startup_header->preboot_size, startup_header->preboot_size, (startup_header->preboot_size == current_offset ? "looks good" : "???")); |
| 2653 | printf (" zero0 = 0x%04x (%d) - zeros - %s\n", startup_header->zero0, startup_header->zero0, (startup_header->zero0 == 0 ? "looks good" : "??? should be zero")); |
2728 | printf (" zero0 = 0x%04x (%d) - zeros - %s\n", startup_header->zero0, startup_header->zero0, (startup_header->zero0 == 0 ? "looks good" : "??? should be zero")); |
| 2654 | printf (" zero[0] = 0x%08x (%d) - zeros - %s\n", startup_header->zero[0], startup_header->zero[0], (startup_header->zero[0] == 0 ? "looks good" : "??? should be zero")); |
2729 | printf (" zero[0] = 0x%08x (%d) - zeros - %s\n", startup_header->zero[0], startup_header->zero[0], (startup_header->zero[0] == 0 ? "looks good" : "??? should be zero")); |
| 2655 | printf (" addr_off = 0x%016llx (%lld) - offset for startup_vaddr and [image|ram|imagefs]_paddr - %s\n", startup_header->addr_off, startup_header->addr_off, (startup_header->addr_off == 0 ? "looks good" : "??? should be zero")); |
2730 | printf (" addr_off = 0x%016llx (%lld) - offset for startup_vaddr and [image|ram|imagefs]_paddr - %s\n", startup_header->addr_off, startup_header->addr_off, (startup_header->addr_off == 0 ? "looks good" : "??? should be zero")); |
| 2656 | hex_printf ((uint8_t *) &startup_header->info[0], sizeof (startup_header->info), " info[48] =\n"); |
2731 | hex_printf ((uint8_t *) &startup_header->info[0], sizeof (startup_header->info), " info[48] =\n"); |
| 2657 | 2732 | ||
| 2658 | // validate that the file can contain up to the startup trailer |
2733 | // validate that the file can contain up to the startup trailer |
| 2659 | if (current_offset + startup_header->startup_size > |
2734 | if (current_offset + startup_header->startup_size > file.len) |
| 2660 | { |
2735 | { |
| 2661 | printf ("WARNING: this IFS file is corrupted (startup trailer extends past end of file)\n"); |
2736 | printf ("WARNING: this IFS file is corrupted (startup trailer extends past end of file)\n"); |
| 2662 | goto endofdata; |
2737 | goto endofdata; |
| 2663 | } |
2738 | } |
| 2664 | 2739 | ||
| Line 2671... | Line 2746... | ||
| 2671 | 2746 | ||
| 2672 | // locate the right startup trailer at the right offset |
2747 | // locate the right startup trailer at the right offset |
| 2673 | if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2) |
2748 | if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2) |
| 2674 | { |
2749 | { |
| 2675 | startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v2_t); |
2750 | startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v2_t); |
| 2676 | startup_trailer_v2 = (startup_trailer_v2_t *) & |
2751 | startup_trailer_v2 = (startup_trailer_v2_t *) &file.bytes[startuptrailer_offset]; |
| 2677 | startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v2_t); |
2752 | startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v2_t); |
| 2678 | } |
2753 | } |
| 2679 | else // old V1 trailer |
2754 | else // old V1 trailer |
| 2680 | { |
2755 | { |
| 2681 | startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v1_t); |
2756 | startuptrailer_offset = current_offset + startup_header->startup_size - sizeof (startup_trailer_v1_t); |
| 2682 | startup_trailer_v1 = (startup_trailer_v1_t *) & |
2757 | startup_trailer_v1 = (startup_trailer_v1_t *) &file.bytes[startuptrailer_offset]; |
| 2683 | startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v1_t); |
2758 | startupfile_blobsize = startup_header->startup_size - sizeof (startup_header_t) - sizeof (startup_trailer_v1_t); |
| 2684 | } |
2759 | } |
| 2685 | 2760 | ||
| 2686 | current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob |
2761 | current_offset += sizeof (startup_header_t); // jump over the startup header and reach the startup blob |
| 2687 | printf ("\n"); |
2762 | printf ("\n"); |
| 2688 | printf ("Startup blob at offset 0x%zx (%zd):\n", current_offset, current_offset); |
2763 | printf ("Startup blob at offset 0x%zx (%zd):\n", current_offset, current_offset); |
| 2689 | printf (" size 0x%zx (%zd) bytes\n", startupfile_blobsize, startupfile_blobsize); |
2764 | printf (" size 0x%zx (%zd) bytes\n", startupfile_blobsize, startupfile_blobsize); |
| 2690 | printf (" checksum %d\n", update_checksum (& |
2765 | printf (" checksum %d\n", update_checksum (&file.bytes[current_offset], startupfile_blobsize, is_foreign_endianness)); |
| 2691 | 2766 | ||
| 2692 | current_offset += startupfile_blobsize; // jump over the startup blob and reach the startup trailer |
2767 | current_offset += startupfile_blobsize; // jump over the startup blob and reach the startup trailer |
| 2693 | printf ("\n"); |
2768 | printf ("\n"); |
| 2694 | printf ("Startup trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? 2 : 1)); |
2769 | printf ("Startup trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? 2 : 1)); |
| 2695 | if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2) |
2770 | if (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2) |
| Line 2717... | Line 2792... | ||
| 2717 | 2792 | ||
| 2718 | current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // now reach the next segment |
2793 | current_offset += (startup_header->flags1 & STARTUP_HDR_FLAGS1_TRAILER_V2 ? sizeof (startup_trailer_v2_t) : sizeof (startup_trailer_v1_t)); // now reach the next segment |
| 2719 | } |
2794 | } |
| 2720 | 2795 | ||
| 2721 | // else does an image header start here ? |
2796 | // else does an image header start here ? |
| 2722 | else if ((current_offset + sizeof (image_header_t) < |
2797 | else if ((current_offset + sizeof (image_header_t) < file.len) && (memcmp (&file.bytes[current_offset], "imagefs", 7) == 0)) |
| 2723 | { |
2798 | { |
| 2724 | imageheader_offset = current_offset; |
2799 | imageheader_offset = current_offset; |
| 2725 | image_header = (image_header_t *) & |
2800 | image_header = (image_header_t *) &file.bytes[imageheader_offset]; |
| 2726 | 2801 | ||
| 2727 | // layout: |
2802 | // layout: |
| 2728 | // [IMAGE HEADER] |
2803 | // [IMAGE HEADER] |
| 2729 | // [image directory entries] |
2804 | // [image directory entries] |
| 2730 | // [smallest file blobs up to KERNEL] |
2805 | // [smallest file blobs up to KERNEL] |
| Line 2735... | Line 2810... | ||
| 2735 | 2810 | ||
| 2736 | printf ("\n"); |
2811 | printf ("\n"); |
| 2737 | printf ("Image header at offset %zx (%zd):\n", current_offset, current_offset); |
2812 | printf ("Image header at offset %zx (%zd):\n", current_offset, current_offset); |
| 2738 | printf (" signature = %02x %02x %02x %02x %02x %02x %02x (\"%.7s\") - good\n", image_header->signature[0], image_header->signature[1], image_header->signature[2], image_header->signature[3], image_header->signature[4], image_header->signature[5], image_header->signature[6], image_header->signature); |
2813 | printf (" signature = %02x %02x %02x %02x %02x %02x %02x (\"%.7s\") - good\n", image_header->signature[0], image_header->signature[1], image_header->signature[2], image_header->signature[3], image_header->signature[4], image_header->signature[5], image_header->signature[6], image_header->signature); |
| 2739 | printf (" flags = 0x%02x (%s)\n", image_header->flags, describe_uint8 (image_header->flags, imageheader_flags_strings)); |
2814 | printf (" flags = 0x%02x (%s)\n", image_header->flags, describe_uint8 (image_header->flags, imageheader_flags_strings)); |
| 2740 | printf (" image_size = 0x%08x (%d) - size from header to end of trailer - %s\n", image_header->image_size, image_header->image_size, (current_offset + image_header->image_size <= |
2815 | printf (" image_size = 0x%08x (%d) - size from header to end of trailer - %s\n", image_header->image_size, image_header->image_size, (current_offset + image_header->image_size <= file.len ? "looks good" : "BAD (IFS file too short)")); |
| 2741 | printf (" hdr_dir_size = 0x%08x (%d) - size from header to last dirent - %s\n", image_header->hdr_dir_size, image_header->hdr_dir_size, (current_offset + image_header->hdr_dir_size < |
2816 | printf (" hdr_dir_size = 0x%08x (%d) - size from header to last dirent - %s\n", image_header->hdr_dir_size, image_header->hdr_dir_size, (current_offset + image_header->hdr_dir_size < file.len ? "looks good" : "BAD (IFS file too short)")); |
| 2742 | printf (" dir_offset = 0x%08x (%d) - offset from header to first dirent - %s\n", image_header->dir_offset, image_header->dir_offset, (current_offset + image_header->dir_offset >= |
2817 | printf (" dir_offset = 0x%08x (%d) - offset from header to first dirent - %s\n", image_header->dir_offset, image_header->dir_offset, (current_offset + image_header->dir_offset >= file.len ? "BAD (IFS file too short)" : (image_header->dir_offset > image_header->hdr_dir_size ? "BAD" : "looks good"))); |
| 2743 | printf (" boot_ino[4] = { 0x%08x, 0x%08x, 0x%08x, 0x%08x }\n", image_header->boot_ino[0], image_header->boot_ino[1], image_header->boot_ino[2], image_header->boot_ino[3]); |
2818 | printf (" boot_ino[4] = { 0x%08x, 0x%08x, 0x%08x, 0x%08x }\n", image_header->boot_ino[0], image_header->boot_ino[1], image_header->boot_ino[2], image_header->boot_ino[3]); |
| 2744 | printf (" script_ino = 0x%08x (%d) - inode of compiled bootscript\n", image_header->script_ino, image_header->script_ino); |
2819 | printf (" script_ino = 0x%08x (%d) - inode of compiled bootscript\n", image_header->script_ino, image_header->script_ino); |
| 2745 | printf (" chain_paddr = 0x%08x (%d) - offset to next fs signature\n", image_header->chain_paddr, image_header->chain_paddr); |
2820 | printf (" chain_paddr = 0x%08x (%d) - offset to next fs signature\n", image_header->chain_paddr, image_header->chain_paddr); |
| 2746 | hex_printf ((uint8_t *) &image_header->spare[0], sizeof (image_header->spare), " spare[10] =\n"); |
2821 | hex_printf ((uint8_t *) &image_header->spare[0], sizeof (image_header->spare), " spare[10] =\n"); |
| 2747 | printf (" mountflags = 0x%08x (%s %s %s %s)\n", image_header->mountflags, BINARY (((uint8_t *) &image_header->mountflags)[0]), BINARY (((uint8_t *) &image_header->mountflags)[1]), BINARY (((uint8_t *) &image_header->mountflags)[2]), BINARY (((uint8_t *) &image_header->mountflags)[3])); |
2822 | printf (" mountflags = 0x%08x (%s %s %s %s)\n", image_header->mountflags, BINARY (((uint8_t *) &image_header->mountflags)[0]), BINARY (((uint8_t *) &image_header->mountflags)[1]), BINARY (((uint8_t *) &image_header->mountflags)[2]), BINARY (((uint8_t *) &image_header->mountflags)[3])); |
| 2748 | printf (" mountpoint = \"%s\"\n", image_header->mountpoint); |
2823 | printf (" mountpoint = \"%s\"\n", image_header->mountpoint); |
| 2749 | 2824 | ||
| 2750 | // validate that the file can contain up to the image trailer |
2825 | // validate that the file can contain up to the image trailer |
| 2751 | if (current_offset + image_header->image_size > |
2826 | if (current_offset + image_header->image_size > file.len) |
| 2752 | { |
2827 | { |
| 2753 | printf ("WARNING: this IFS file is corrupted (image trailer extends past end of file)\n"); |
2828 | printf ("WARNING: this IFS file is corrupted (image trailer extends past end of file)\n"); |
| 2754 | goto endofdata; |
2829 | goto endofdata; |
| 2755 | } |
2830 | } |
| 2756 | 2831 | ||
| Line 2763... | Line 2838... | ||
| 2763 | 2838 | ||
| 2764 | // locate the image trailer at the right offset |
2839 | // locate the image trailer at the right offset |
| 2765 | if (image_header->flags & IMAGE_FLAGS_TRAILER_V2) |
2840 | if (image_header->flags & IMAGE_FLAGS_TRAILER_V2) |
| 2766 | { |
2841 | { |
| 2767 | imagetrailer_offset = current_offset + image_header->image_size - sizeof (image_trailer_v2_t); |
2842 | imagetrailer_offset = current_offset + image_header->image_size - sizeof (image_trailer_v2_t); |
| 2768 | image_trailer_v2 = (image_trailer_v2_t *) & |
2843 | image_trailer_v2 = (image_trailer_v2_t *) &file.bytes[imagetrailer_offset]; |
| 2769 | } |
2844 | } |
| 2770 | else // old V1 trailer |
2845 | else // old V1 trailer |
| 2771 | { |
2846 | { |
| 2772 | imagetrailer_offset = current_offset + image_header->image_size - sizeof (image_trailer_v1_t); |
2847 | imagetrailer_offset = current_offset + image_header->image_size - sizeof (image_trailer_v1_t); |
| 2773 | image_trailer_v1 = (image_trailer_v1_t *) & |
2848 | image_trailer_v1 = (image_trailer_v1_t *) &file.bytes[imagetrailer_offset]; |
| 2774 | } |
2849 | } |
| 2775 | 2850 | ||
| 2776 | current_offset += sizeof (image_header_t); // jump over the image header and reach the first directory entry |
2851 | current_offset += sizeof (image_header_t); // jump over the image header and reach the first directory entry |
| 2777 | 2852 | ||
| 2778 | // there may be padding before the first directory entry |
2853 | // there may be padding before the first directory entry |
| 2779 | if (image_header->dir_offset - sizeof (image_header_t) > 0) |
2854 | if (image_header->dir_offset - sizeof (image_header_t) > 0) |
| 2780 | hex_printf (& |
2855 | hex_printf (&file.bytes[current_offset], image_header->dir_offset - sizeof (image_header_t), "\n" "%zd padding bytes at offset 0x%zd (%zd):\n", image_header->dir_offset - sizeof (image_header_t), current_offset, current_offset); |
| 2781 | current_offset += image_header->dir_offset - sizeof (image_header_t); // padding was processed, jump over it |
2856 | current_offset += image_header->dir_offset - sizeof (image_header_t); // padding was processed, jump over it |
| 2782 | 2857 | ||
| 2783 | // dump all directory entries until the last one included |
2858 | // dump all directory entries until the last one included |
| 2784 | fsentries = NULL; |
2859 | fsentries = NULL; |
| 2785 | fsentry_count = 0; |
2860 | fsentry_count = 0; |
| 2786 | while (current_offset < imageheader_offset + image_header->hdr_dir_size) |
2861 | while (current_offset < imageheader_offset + image_header->hdr_dir_size) |
| 2787 | { |
2862 | { |
| 2788 | current_fsentry = (fsentry_t *) & |
2863 | current_fsentry = (fsentry_t *) &file.bytes[current_offset]; |
| 2789 | 2864 | ||
| 2790 | if (imageheader_offset + image_header->hdr_dir_size - current_offset < sizeof (current_fsentry->header)) |
2865 | if (imageheader_offset + image_header->hdr_dir_size - current_offset < sizeof (current_fsentry->header)) |
| 2791 | break; // end padding reached |
2866 | break; // end padding reached |
| 2792 | 2867 | ||
| 2793 | // stack up the filesystem entry pointers in an array while we read them |
2868 | // stack up the filesystem entry pointers in an array while we read them |
| Line 2797... | Line 2872... | ||
| 2797 | fsentries[fsentry_count] = current_fsentry; |
2872 | fsentries[fsentry_count] = current_fsentry; |
| 2798 | fsentry_count++; |
2873 | fsentry_count++; |
| 2799 | 2874 | ||
| 2800 | printf ("\n"); |
2875 | printf ("\n"); |
| 2801 | printf ("Filesystem entry at offset 0x%zx (%zd) - last one at 0x%zd (%zd):\n", current_offset, current_offset, imageheader_offset + image_header->hdr_dir_size, imageheader_offset + image_header->hdr_dir_size); |
2876 | printf ("Filesystem entry at offset 0x%zx (%zd) - last one at 0x%zd (%zd):\n", current_offset, current_offset, imageheader_offset + image_header->hdr_dir_size, imageheader_offset + image_header->hdr_dir_size); |
| 2802 | printf (" size = 0x%04x (%d) - size of dirent - %s\n", current_fsentry->header.size, current_fsentry->header.size, ((current_fsentry->header.size > 0) && (current_offset + current_fsentry->header.size < |
2877 | printf (" size = 0x%04x (%d) - size of dirent - %s\n", current_fsentry->header.size, current_fsentry->header.size, ((current_fsentry->header.size > 0) && (current_offset + current_fsentry->header.size < file.len) ? "looks good" : "BAD")); |
| 2803 | printf (" extattr_offset = 0x%04x (%d) - %s\n", current_fsentry->header.extattr_offset, current_fsentry->header.extattr_offset, (current_fsentry->header.extattr_offset == 0 ? "no extattr" : "has extattr")); |
2878 | printf (" extattr_offset = 0x%04x (%d) - %s\n", current_fsentry->header.extattr_offset, current_fsentry->header.extattr_offset, (current_fsentry->header.extattr_offset == 0 ? "no extattr" : "has extattr")); |
| 2804 | printf (" ino = 0x%08x (%d) - inode number (%s%s%s%s)\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "is" : "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" : "")); |
2879 | printf (" ino = 0x%08x (%d) - inode number (%s%s%s%s)\n", current_fsentry->header.ino, current_fsentry->header.ino, (current_fsentry->header.ino & 0xE0000000 ? "is" : "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" : "")); |
| 2805 | printf (" mode = 0x%08x (%d) - %s (0%o), POSIX permissions 0%o\n", current_fsentry->header.mode, current_fsentry->header.mode, (S_ISDIR (current_fsentry->header.mode) ? "directory" : (S_ISREG (current_fsentry->header.mode) ? "file" : (S_ISLNK (current_fsentry->header.mode) ? "symlink" : "device"))), (current_fsentry->header.mode & 0xF000) >> 12, current_fsentry->header.mode & 0xFFF); |
2880 | printf (" mode = 0x%08x (%d) - %s (0%o), POSIX permissions 0%o\n", current_fsentry->header.mode, current_fsentry->header.mode, (S_ISDIR (current_fsentry->header.mode) ? "directory" : (S_ISREG (current_fsentry->header.mode) ? "file" : (S_ISLNK (current_fsentry->header.mode) ? "symlink" : "device"))), (current_fsentry->header.mode & 0xF000) >> 12, current_fsentry->header.mode & 0xFFF); |
| 2806 | printf (" gid = 0x%08x (%d) - owner group ID%s\n", current_fsentry->header.gid, current_fsentry->header.gid, (current_fsentry->header.gid == 0 ? " (root)" : "")); |
2881 | printf (" gid = 0x%08x (%d) - owner group ID%s\n", current_fsentry->header.gid, current_fsentry->header.gid, (current_fsentry->header.gid == 0 ? " (root)" : "")); |
| 2807 | printf (" uid = 0x%08x (%d) - owner user ID%s\n", current_fsentry->header.uid, current_fsentry->header.uid, (current_fsentry->header.uid == 0 ? " (root)" : "")); |
2882 | printf (" uid = 0x%08x (%d) - owner user ID%s\n", current_fsentry->header.uid, current_fsentry->header.uid, (current_fsentry->header.uid == 0 ? " (root)" : "")); |
| Line 2809... | Line 2884... | ||
| 2809 | printf (" mtime = 0x%08x (%d) - POSIX timestamp: %s", current_fsentry->header.mtime, current_fsentry->header.mtime, asctime (localtime (&mtime))); // NOTE: asctime() provides the newline |
2884 | printf (" mtime = 0x%08x (%d) - POSIX timestamp: %s", current_fsentry->header.mtime, current_fsentry->header.mtime, asctime (localtime (&mtime))); // NOTE: asctime() provides the newline |
| 2810 | if (S_ISDIR (current_fsentry->header.mode)) |
2885 | if (S_ISDIR (current_fsentry->header.mode)) |
| 2811 | printf (" [DIRECTORY] path = \"%s\"\n", (char *) ¤t_fsentry->u.dir.path); // convert from pointer to char array |
2886 | printf (" [DIRECTORY] path = \"%s\"\n", (char *) ¤t_fsentry->u.dir.path); // convert from pointer to char array |
| 2812 | else if (S_ISREG (current_fsentry->header.mode)) |
2887 | else if (S_ISREG (current_fsentry->header.mode)) |
| 2813 | { |
2888 | { |
| 2814 | printf (" [FILE] offset = 0x%08x (%d) - %s\n", current_fsentry->u.file.offset, current_fsentry->u.file.offset, (imageheader_offset + current_fsentry->u.file.offset < |
2889 | printf (" [FILE] offset = 0x%08x (%d) - %s\n", current_fsentry->u.file.offset, current_fsentry->u.file.offset, (imageheader_offset + current_fsentry->u.file.offset < file.len ? "looks good" : "BAD (IFS file too short)")); |
| 2815 | printf (" [FILE] size = 0x%08x (%d) - %s\n", current_fsentry->u.file.size, current_fsentry->u.file.size, (imageheader_offset + current_fsentry->u.file.offset + current_fsentry->u.file.size < |
2890 | printf (" [FILE] size = 0x%08x (%d) - %s\n", current_fsentry->u.file.size, current_fsentry->u.file.size, (imageheader_offset + current_fsentry->u.file.offset + current_fsentry->u.file.size < file.len ? "looks good" : "BAD (IFS file too short)")); |
| 2816 | printf (" [FILE] path = \"%s\"\n", (char *) ¤t_fsentry->u.file.path); // convert from pointer to char array |
2891 | printf (" [FILE] path = \"%s\"\n", (char *) ¤t_fsentry->u.file.path); // convert from pointer to char array |
| 2817 | } |
2892 | } |
| 2818 | else if (S_ISLNK (current_fsentry->header.mode)) |
2893 | else if (S_ISLNK (current_fsentry->header.mode)) |
| 2819 | { |
2894 | { |
| 2820 | printf (" [SYMLINK] sym_offset = 0x%04x (%d) - %s\n", current_fsentry->u.symlink.sym_offset, current_fsentry->u.symlink.sym_offset, (sizeof (current_fsentry->header) + 2 * sizeof (uint16_t) + current_fsentry->u.symlink.sym_offset <= current_fsentry->header.size ? "looks good" : "BAD (dirent too short)")); |
2895 | printf (" [SYMLINK] sym_offset = 0x%04x (%d) - %s\n", current_fsentry->u.symlink.sym_offset, current_fsentry->u.symlink.sym_offset, (sizeof (current_fsentry->header) + 2 * sizeof (uint16_t) + current_fsentry->u.symlink.sym_offset <= current_fsentry->header.size ? "looks good" : "BAD (dirent too short)")); |
| Line 2827... | Line 2902... | ||
| 2827 | printf (" [DEVICE] dev = 0x%08x (%d)\n", current_fsentry->u.device.dev, current_fsentry->u.device.dev); |
2902 | printf (" [DEVICE] dev = 0x%08x (%d)\n", current_fsentry->u.device.dev, current_fsentry->u.device.dev); |
| 2828 | printf (" [DEVICE] rdev = 0x%08x (%d)\n", current_fsentry->u.device.rdev, current_fsentry->u.device.rdev); |
2903 | printf (" [DEVICE] rdev = 0x%08x (%d)\n", current_fsentry->u.device.rdev, current_fsentry->u.device.rdev); |
| 2829 | printf (" [DEVICE] path = \"%s\"\n", (char *) ¤t_fsentry->u.device.path); // convert from pointer to char array |
2904 | printf (" [DEVICE] path = \"%s\"\n", (char *) ¤t_fsentry->u.device.path); // convert from pointer to char array |
| 2830 | } |
2905 | } |
| 2831 | 2906 | ||
| 2832 | if ((current_fsentry->header.size == 0) || (current_offset + current_fsentry->header.size >= |
2907 | if ((current_fsentry->header.size == 0) || (current_offset + current_fsentry->header.size >= file.len)) |
| 2833 | { |
2908 | { |
| 2834 | printf ("WARNING: this IFS file is corrupted (the size of this directory entry is invalid)\n"); |
2909 | printf ("WARNING: this IFS file is corrupted (the size of this directory entry is invalid)\n"); |
| 2835 | goto endofdata; |
2910 | goto endofdata; |
| 2836 | } |
2911 | } |
| 2837 | 2912 | ||
| 2838 | current_offset += current_fsentry->header.size; |
2913 | current_offset += current_fsentry->header.size; |
| 2839 | } |
2914 | } |
| 2840 | if (imageheader_offset + image_header->hdr_dir_size < current_offset + sizeof (current_fsentry->header)) |
2915 | if (imageheader_offset + image_header->hdr_dir_size < current_offset + sizeof (current_fsentry->header)) |
| 2841 | hex_printf (& |
2916 | hex_printf (&file.bytes[current_offset], imageheader_offset + image_header->hdr_dir_size - current_offset, "\n" "%zd padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + image_header->hdr_dir_size - current_offset, current_offset, current_offset); |
| 2842 | current_offset += imageheader_offset + image_header->hdr_dir_size - current_offset; // padding was processed, jump over it |
2917 | current_offset += imageheader_offset + image_header->hdr_dir_size - current_offset; // padding was processed, jump over it |
| 2843 | 2918 | ||
| 2844 | // at this point we are past the directory entries; what is stored now, up to and until the image trailer, is the files' data |
2919 | // at this point we are past the directory entries; what is stored now, up to and until the image trailer, is the files' data |
| 2845 | if (fsentry_count > 0) |
2920 | if (fsentry_count > 0) |
| 2846 | { |
2921 | { |
| Line 2862... | Line 2937... | ||
| 2862 | fsentry_index = nearest_index; |
2937 | fsentry_index = nearest_index; |
| 2863 | current_fsentry = fsentries[fsentry_index]; // quick access to closest fsentry |
2938 | current_fsentry = fsentries[fsentry_index]; // quick access to closest fsentry |
| 2864 | 2939 | ||
| 2865 | // there may be padding before the file data |
2940 | // there may be padding before the file data |
| 2866 | if (imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset > 0) |
2941 | if (imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset > 0) |
| 2867 | hex_printf (& |
2942 | hex_printf (&file.bytes[current_offset], imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, "\n" "%zd padding bytes at offset 0x%zx (%zd):\n", imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset, current_offset, current_offset); |
| 2868 | current_offset += imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset; // padding was processed, jump over it |
2943 | current_offset += imageheader_offset + (size_t) current_fsentry->u.file.offset - current_offset; // padding was processed, jump over it |
| 2869 | 2944 | ||
| 2870 | printf ("\n"); |
2945 | printf ("\n"); |
| 2871 | printf ("File data blob at offset 0x%zx (%zd):\n", current_offset, current_offset); |
2946 | printf ("File data blob at offset 0x%zx (%zd):\n", current_offset, current_offset); |
| 2872 | printf (" corresponding dirent index: %zd/%zd\n", fsentry_index, fsentry_count); |
2947 | printf (" corresponding dirent index: %zd/%zd\n", fsentry_index, fsentry_count); |
| 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" : "")); |
2948 | 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" : "")); |
| 2874 | printf (" corresponding path: \"%s\"\n", (char *) ¤t_fsentry->u.file.path); // convert from pointer to char array |
2949 | printf (" corresponding path: \"%s\"\n", (char *) ¤t_fsentry->u.file.path); // convert from pointer to char array |
| 2875 | printf (" size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size); |
2950 | printf (" size 0x%zx (%zd) bytes\n", (size_t) current_fsentry->u.file.size, (size_t) current_fsentry->u.file.size); |
| 2876 | if (current_offset + 4 < |
2951 | if (current_offset + 4 < file.len) |
| 2877 | hex_printf (& |
2952 | hex_printf (&file.bytes[current_offset], current_fsentry->u.file.size, " data:\n"); |
| 2878 | if (current_offset + current_fsentry->u.file.size < |
2953 | if (current_offset + current_fsentry->u.file.size < file.len) |
| 2879 | printf (" checksum %d\n", update_checksum (& |
2954 | printf (" checksum %d\n", update_checksum (&file.bytes[current_offset], current_fsentry->u.file.size, is_foreign_endianness)); |
| 2880 | else |
2955 | else |
| 2881 | { |
2956 | { |
| 2882 | printf ("WARNING: this IFS file is corrupted (the size of this file data extends past the IFS size)\n"); |
2957 | printf ("WARNING: this IFS file is corrupted (the size of this file data extends past the IFS size)\n"); |
| 2883 | goto endofdata; |
2958 | goto endofdata; |
| 2884 | } |
2959 | } |
| Line 2887... | Line 2962... | ||
| 2887 | } |
2962 | } |
| 2888 | } |
2963 | } |
| 2889 | 2964 | ||
| 2890 | // ad this point we're past the last file data, there may be padding before the image trailer |
2965 | // ad this point we're past the last file data, there may be padding before the image trailer |
| 2891 | if (imagetrailer_offset - current_offset > 0) |
2966 | if (imagetrailer_offset - current_offset > 0) |
| 2892 | hex_printf (& |
2967 | hex_printf (&file.bytes[current_offset], imagetrailer_offset - current_offset, "\n" "%zd padding bytes at offset %zx (%zd):\n", imagetrailer_offset - current_offset, current_offset, current_offset); |
| 2893 | current_offset += imagetrailer_offset - current_offset; // padding was processed, jump over it |
2968 | current_offset += imagetrailer_offset - current_offset; // padding was processed, jump over it |
| 2894 | 2969 | ||
| 2895 | printf ("\n"); |
2970 | printf ("\n"); |
| 2896 | printf ("Image trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? 2 : 1)); |
2971 | printf ("Image trailer at offset 0x%zx (%zd) - version %d:\n", current_offset, current_offset, (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? 2 : 1)); |
| 2897 | if (image_header->flags & IMAGE_FLAGS_TRAILER_V2) |
2972 | if (image_header->flags & IMAGE_FLAGS_TRAILER_V2) |
| Line 2922... | Line 2997... | ||
| 2922 | 2997 | ||
| 2923 | // else it has to be a boot blob, of which we don't know the size, except that it has to fit in 0xffff bytes and be immediately followed by a startup header |
2998 | // else it has to be a boot blob, of which we don't know the size, except that it has to fit in 0xffff bytes and be immediately followed by a startup header |
| 2924 | else |
2999 | else |
| 2925 | { |
3000 | { |
| 2926 | // so scan for the first startup header magic and version (which makes us 6 bytes to scan for, i.e. "\xeb\x7e\xff\x00" for the magic and "\x01\x00" (LSB) for the version 1) |
3001 | // so scan for the first startup header magic and version (which makes us 6 bytes to scan for, i.e. "\xeb\x7e\xff\x00" for the magic and "\x01\x00" (LSB) for the version 1) |
| 2927 | for (byte_index = current_offset; byte_index < |
3002 | for (byte_index = current_offset; byte_index < file.len - 6; byte_index++) |
| 2928 | if (memcmp (& |
3003 | if (memcmp (&file.bytes[byte_index], "\xeb\x7e\xff\x00" "\x01\x00", 4 + 2) == 0) |
| 2929 | break; // stop as soon as we find it |
3004 | break; // stop as soon as we find it |
| 2930 | 3005 | ||
| 2931 | if (byte_index >= |
3006 | if (byte_index >= file.len - 6) |
| 2932 | break; // if not found, stop scanning |
3007 | break; // if not found, stop scanning |
| 2933 | 3008 | ||
| 2934 | bootfile_blobsize = byte_index - current_offset; |
3009 | bootfile_blobsize = byte_index - current_offset; |
| 2935 | printf ("Boot blob at offset 0x%zx (%zd):\n", current_offset, current_offset); |
3010 | printf ("Boot blob at offset 0x%zx (%zd):\n", current_offset, current_offset); |
| 2936 | printf (" size 0x%zx (%zd) bytes\n", bootfile_blobsize, bootfile_blobsize); |
3011 | printf (" size 0x%zx (%zd) bytes\n", bootfile_blobsize, bootfile_blobsize); |
| 2937 | printf (" checksum 0x%08x\n", update_checksum (& |
3012 | printf (" checksum 0x%08x\n", update_checksum (&file.bytes[current_offset], bootfile_blobsize, false)); // NOTE: endianness is not known yet -- assume same |
| 2938 | 3013 | ||
| 2939 | current_offset = byte_index; // now reach the next segment |
3014 | current_offset = byte_index; // now reach the next segment |
| 2940 | } |
3015 | } |
| 2941 | } |
3016 | } |
| 2942 | 3017 | ||
| 2943 | endofdata: |
3018 | endofdata: |
| 2944 | // at this point there's nothing left we're able to parse |
3019 | // at this point there's nothing left we're able to parse |
| 2945 | if (current_offset < |
3020 | if (current_offset < file.len) |
| 2946 | { |
3021 | { |
| 2947 | printf ("End of identifiable data reached.\n"); |
3022 | printf ("End of identifiable data reached.\n"); |
| 2948 | hex_printf (& |
3023 | hex_printf (&file.bytes[current_offset], file.len - current_offset, "\n" "%zd extra bytes at offset %zx (%zd):\n", file.len - current_offset, current_offset, current_offset); |
| 2949 | } |
3024 | } |
| 2950 | 3025 | ||
| 2951 | printf ("End of file reached at offset 0x%zx (%zd)\n", |
3026 | printf ("End of file reached at offset 0x%zx (%zd)\n", file.len, file.len); |
| 2952 | printf ("IFS dissecation complete.\n"); |
3027 | printf ("IFS dissecation complete.\n"); |
| 2953 | return (0); |
3028 | return (0); |
| 2954 | } |
3029 | } |