Rev 8 | Rev 10 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 8 | Rev 9 | ||
---|---|---|---|
Line 120... | Line 120... | ||
120 | #define PATH_SEP_STR ":" |
120 | #define PATH_SEP_STR ":" |
121 | #endif // _WIN32 |
121 | #endif // _WIN32 |
122 | #define RECORD_SEP '\x1e' // ASCII record separator |
122 | #define RECORD_SEP '\x1e' // ASCII record separator |
123 | #define RECORD_SEP_STR "\x1e" // ASCII record separator (as string) |
123 | #define RECORD_SEP_STR "\x1e" // ASCII record separator (as string) |
124 | 124 | ||
- | 125 | // macros for accessing ELF files |
|
125 | #define ELF_MAGIC_STR "\x7f" "ELF" |
126 | #define ELF_MAGIC_STR "\x7f" "ELF" |
126 | #define ELF_ENDIAN_LITTLE 1 // ELF file is little endian |
127 | #define ELF_ENDIAN_LITTLE 1 // ELF file is little endian |
127 | #define ELF_ENDIAN_BIG 2 // ELF file is big endian |
128 | #define ELF_ENDIAN_BIG 2 // ELF file is big endian |
128 | #define ELF_DT_NULL 0 // marks end of dynamic section |
129 | #define ELF_DT_NULL 0 // marks end of dynamic section |
129 | #define ELF_DT_SONAME 14 // canonical name of shared object |
130 | #define ELF_DT_SONAME 14 // canonical name of shared object |
- | 131 | #define ELF_STRUCT_MEMBER_NUMERIC(elfhdr,elfstruct,member) ((elfhdr)->u.elf.platform_size == 2 ? /* is it a 64-bit ELF file ? */ \ |
|
- | 132 | ( \ |
|
130 |
|
133 | (sizeof ((elfstruct)->u.elf64.member) == 1) || (((elfhdr)->u.elf.endianness == 1) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || (((elfhdr)->u.elf.endianness == 2) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) ? /* single-byte, or same endianness ? */ \ |
- | 134 | (elfstruct)->u.elf64.member /* same endianness, or single byte required: don't swap */ \ |
|
- | 135 | : /* else */ \ |
|
131 |
|
136 | (sizeof ((elfstruct)->u.elf64.member) == 8 ? __builtin_bswap64 ((elfstruct)->u.elf64.member) : (sizeof ((elfstruct)->u.elf64.member) == 4 ? __builtin_bswap32 ((elfstruct)->u.elf64.member) : __builtin_bswap16 ((elfstruct)->u.elf64.member))) /* different endianness: swap */ \ |
- | 137 | ) \ |
|
- | 138 | : /* else peek at 32-bit ELF */ \ |
|
- | 139 | ( \ |
|
132 |
|
140 | (sizeof ((elfstruct)->u.elf32.member) == 1) || (((elfhdr)->u.elf.endianness == 1) && (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) || (((elfhdr)->u.elf.endianness == 2) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) ? /* single-byte, or same endianness ? */ \ |
- | 141 | (elfstruct)->u.elf32.member /* same endianness, or single byte required: don't swap */ \ |
|
- | 142 | : /* else */ \ |
|
- | 143 | (sizeof ((elfstruct)->u.elf32.member) == 4 ? __builtin_bswap32 ((elfstruct)->u.elf32.member) : __builtin_bswap16 ((elfstruct)->u.elf32.member)) /* different endianness: swap */ \ |
|
- | 144 | ) \ |
|
- | 145 | ) // this macro supports 32- and 64-bit ELF files in low and big endianness transparently |
|
- | 146 | #define ELF_STRUCT_MEMBER_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 |
|
- | 147 | #define ELF_STRUCT_SIZE(elfhdr,elfstruct) ((elfhdr)->u.elf.platform_size == 2 ? sizeof ((elfstruct)->u.elf64) : sizeof ((elfstruct)->u.elf32)) // this macro supports 32- and 64-bit ELF files transparently |
|
133 | 148 | ||
134 | #define WILL_BE_FILLED_LATER 0xbaadf00d |
149 | #define WILL_BE_FILLED_LATER 0xbaadf00d |
135 | 150 | ||
136 | 151 | ||
137 | // bitmapped flags used in the flags1 member of the startup header |
152 | // bitmapped flags used in the flags1 member of the startup header |
Line 1192... | Line 1207... | ||
1192 | if (entry_parms->mtime == UINT32_MAX) |
1207 | if (entry_parms->mtime == UINT32_MAX) |
1193 | entry_parms->mtime = (uint32_t) stat_buf.st_mtime; |
1208 | entry_parms->mtime = (uint32_t) stat_buf.st_mtime; |
1194 | 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->datalen); |
1209 | 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->datalen); |
1195 | } |
1210 | } |
1196 | 1211 | ||
1197 | // is the file we're storing |
1212 | // is the file we're storing an ELF file ? |
1198 | if ((entry_parms->datalen > 52) // file is big enough to contain an ELF header |
1213 | if ((entry_parms->datalen > 52) // file is big enough to contain an ELF header |
1199 | && ((elf = (elf_header_t *) entry_parms->data) != NULL) // cast (necessary true) |
1214 | && ((elf = (elf_header_t *) entry_parms->data) != NULL) // cast (necessary true) |
1200 | && (memcmp ( |
1215 | && (memcmp (ELF_STRUCT_MEMBER_STRING (elf, elf, magic), ELF_MAGIC_STR, 4) == 0)) // file starts with the ELF magic |
1201 | && ( ((ELF_HDR_MEMBER (elf, endianness) == ELF_ENDIAN_LITTLE) && (ELF_HDR_MEMBER (elf, type) == 3)) // file is little endian (offset 5) AND relocatable executable (i.e. a dynamic library) |
- | |
1202 | || ((ELF_HDR_MEMBER (elf, endianness) == ELF_ENDIAN_BIG) && (__builtin_bswap16 (ELF_HDR_MEMBER (elf, type)) == 3))) // file is big endian (offset 5) AND relocatable executable (i.e. a dynamic library) |
- | |
1203 | && entry_parms->should_autosymlink_dylib) // we should store it under its official .so name |
- | |
1204 | { |
1216 | { |
1205 | // |
1217 | shdr_shstr = (elf_section_header_t *) &entry_parms->data[ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_table_offset) + (size_t) ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_item_size) * ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_names_idx)]; // quick access to section header for the section that contains the section names |
1206 |
|
1218 | shtable_strings = &entry_parms->data[ELF_STRUCT_MEMBER_NUMERIC (elf, shdr_shstr, file_offset)]; // locate the start of the strings table that contains the section names |
1207 | 1219 | ||
1208 |
|
1220 | // strip this ELF file |
1209 | shtable_strings = &entry_parms->data[ELF_STRUCT_MEMBER (elf, shdr_shstr, file_offset)]; // locate the start of the strings table that contains the section names |
- | |
1210 | 1221 | ||
1211 | // |
1222 | // is the file we're storing a relocatable executable (i.e. a dynamic library) and should we check for its canonical name ? |
1212 |
|
1223 | if ((ELF_STRUCT_MEMBER_NUMERIC (elf, elf, type) == 3) && entry_parms->should_autosymlink_dylib) |
1213 | shdr_dynamic = NULL; |
- | |
1214 | shdr_dynstr = NULL; |
- | |
1215 | for (table_index = 0; table_index < table_count; table_index++) |
- | |
1216 | { |
1224 | { |
1217 | shdr = (elf_section_header_t *) &entry_parms->data[ELF_HDR_MEMBER (elf, section_header_table_offset) + (size_t) ELF_HDR_MEMBER (elf, section_header_item_size) * table_index]; // quick access to section header |
- | |
1218 | elf_section_name = &shtable_strings[ELF_STRUCT_MEMBER (elf, shdr, name_offset)]; |
- | |
1219 |
|
1225 | // we need to find the SONAME of this library |
1220 |
|
1226 | canonical_dylib_name = NULL; |
1221 | else if (strcmp (elf_section_name, ".dynstr") == 0) |
- | |
1222 | shdr_dynstr = shdr; |
- | |
1223 | } |
- | |
1224 | 1227 | ||
1225 | // |
1228 | // locate the sections we need (the dynamic section and its strings table) |
- | 1229 | table_count = ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_table_len); |
|
- | 1230 | shdr_dynamic = NULL; |
|
1226 |
|
1231 | shdr_dynstr = NULL; |
- | 1232 | for (table_index = 0; table_index < table_count; table_index++) |
|
1227 | { |
1233 | { |
1228 |
|
1234 | shdr = (elf_section_header_t *) &entry_parms->data[ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_table_offset) + (size_t) ELF_STRUCT_MEMBER_NUMERIC (elf, elf, section_header_item_size) * table_index]; // quick access to section header |
- | 1235 | elf_section_name = &shtable_strings[ELF_STRUCT_MEMBER_NUMERIC (elf, shdr, name_offset)]; |
|
- | 1236 | if (strcmp (elf_section_name, ".dynamic") == 0) |
|
- | 1237 | shdr_dynamic = shdr; |
|
- | 1238 | else if (strcmp (elf_section_name, ".dynstr") == 0) |
|
- | 1239 | shdr_dynstr = shdr; |
|
- | 1240 | } |
|
1229 | 1241 | ||
1230 | // |
1242 | // make sure we have both the dynamic section header and its own strings table header |
1231 | for (dynamic_entry = (elf_dynamic_section_entry_t *) &entry_parms->data[ELF_STRUCT_MEMBER (elf, shdr_dynamic, file_offset)]; |
- | |
1232 | (ELF_STRUCT_MEMBER (elf, dynamic_entry, tag) != ELF_DT_NULL); |
- | |
1233 | dynamic_entry = (elf_dynamic_section_entry_t *) ((uint8_t *) dynamic_entry + ELF_STRUCT_SIZE (elf, dynamic_entry))) |
- | |
1234 | if (ELF_STRUCT_MEMBER (elf, dynamic_entry, tag) == ELF_DT_SONAME) |
- | |
1235 | { |
- | |
1236 | canonical_dylib_name = dynamic_strings + ELF_STRUCT_MEMBER (elf, dynamic_entry, value.as_integer); |
- | |
1237 | break; |
- | |
1238 | } |
- | |
1239 | - | ||
1240 | // do we have it ? |
- | |
1241 | if (( |
1243 | if ((shdr_dynamic != NULL) && (shdr_dynstr != NULL)) |
1242 | { |
1244 | { |
- | 1245 | dynamic_strings = (char *) &entry_parms->data[ELF_STRUCT_MEMBER_NUMERIC (elf, shdr_dynstr, file_offset)]; // quick access to dynamic sections strings table |
|
- | 1246 | ||
- | 1247 | // walk through the dynamic section, look for the DT_SONAME entry |
|
- | 1248 | for (dynamic_entry = (elf_dynamic_section_entry_t *) &entry_parms->data[ELF_STRUCT_MEMBER_NUMERIC (elf, shdr_dynamic, file_offset)]; |
|
1243 |
|
1249 | (ELF_STRUCT_MEMBER_NUMERIC (elf, dynamic_entry, tag) != ELF_DT_NULL); |
- | 1250 | dynamic_entry = (elf_dynamic_section_entry_t *) ((uint8_t *) dynamic_entry + ELF_STRUCT_SIZE (elf, dynamic_entry))) |
|
- | 1251 | if (ELF_STRUCT_MEMBER_NUMERIC (elf, dynamic_entry, tag) == ELF_DT_SONAME) |
|
- | 1252 | { |
|
- | 1253 | canonical_dylib_name = dynamic_strings + ELF_STRUCT_MEMBER_NUMERIC (elf, dynamic_entry, value.as_integer); |
|
- | 1254 | break; |
|
- | 1255 | } |
|
- | 1256 | ||
- | 1257 | // do we have it ? |
|
1244 | if ( |
1258 | if ((canonical_dylib_name != NULL) && (canonical_dylib_name[0] != 0)) |
1245 | { |
1259 | { |
- | 1260 | sprintf (candidate_pathname, "%s/%s", entry_parms->prefix, canonical_dylib_name); |
|
- | 1261 | if (strcmp (candidate_pathname, stored_pathname) != 0) // claimed dylib name differs from passed name ? |
|
- | 1262 | { |
|
1246 | original_stored_pathname = stored_pathname; // if so, remember to create a symlink here |
1263 | original_stored_pathname = stored_pathname; // if so, remember to create a symlink here |
1247 | stored_pathname = candidate_pathname; |
1264 | stored_pathname = candidate_pathname; |
- | 1265 | } |
|
1248 | } |
1266 | } |
1249 | } |
1267 | } |
1250 | } |
1268 | } // end if the file we're storing is a dylib |
1251 | } |
1269 | } // end if the file we're storing is an ELF file |
1252 | } |
1270 | } |
1253 | else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ? |
1271 | else if (S_ISLNK (entry_parms->st_mode)) // else are we storing a symbolic link ? |
1254 | 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); |
1272 | fprintf (stderr, "symlink: ino 0x%x uid %d gid %d mode 0%o path \"%s\" -> \"%s\"\n", inode_count + 1, entry_parms->uid, entry_parms->gid, entry_parms->st_mode, stored_pathname, entry_parms->data); |
1255 | else // we must be storing a FIFO |
1273 | else // we must be storing a FIFO |
1256 | { |
1274 | { |
Line 2275... | Line 2293... | ||
2275 | sprintf (&recorded_sha512[2 * byte_index], "%02x", startup_trailer_v2->sha512[byte_index]); |
2293 | sprintf (&recorded_sha512[2 * byte_index], "%02x", startup_trailer_v2->sha512[byte_index]); |
2276 | strcpy (computed_sha512, SHA512 (startup_header, startuptrailer_offset - startupheader_offset, NULL)); |
2294 | strcpy (computed_sha512, SHA512 (startup_header, startuptrailer_offset - startupheader_offset, NULL)); |
2277 | recorded_checksum = startup_trailer_v2->cksum; |
2295 | recorded_checksum = startup_trailer_v2->cksum; |
2278 | computed_checksum = update_checksum (startup_header, startuptrailer_offset + SHA512_DIGEST_LENGTH - startupheader_offset, is_foreign_endianness); |
2296 | computed_checksum = update_checksum (startup_header, startuptrailer_offset + SHA512_DIGEST_LENGTH - startupheader_offset, is_foreign_endianness); |
2279 | printf (" sha512([0x%zx-0x%zx[) = %s - %s\n", startupheader_offset, startuptrailer_offset, recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD")); |
2297 | printf (" sha512([0x%zx-0x%zx[) = %s - %s\n", startupheader_offset, startuptrailer_offset, recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD")); |
2280 | printf (" cksum([0x%zx-0x%zx[) = 0x%08x |
2298 | printf (" cksum([0x%zx-0x%zx[) = 0x%08x - %s\n", startupheader_offset, startuptrailer_offset + SHA512_DIGEST_LENGTH, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD")); |
2281 | if (strcasecmp (computed_sha512, recorded_sha512) != 0) |
2299 | if (strcasecmp (computed_sha512, recorded_sha512) != 0) |
2282 | printf ("Computed SHA-512: %s\n", computed_sha512); |
2300 | printf ("Computed SHA-512: %s\n", computed_sha512); |
2283 | if (computed_checksum != recorded_checksum) |
2301 | if (computed_checksum != recorded_checksum) |
2284 | printf ("Computed cksum: 0x%08x |
2302 | printf ("Computed cksum: 0x%08x\n", computed_checksum); |
2285 | } |
2303 | } |
2286 | else // old v1 trailer |
2304 | else // old v1 trailer |
2287 | { |
2305 | { |
2288 | recorded_checksum = startup_trailer_v1->cksum; |
2306 | recorded_checksum = startup_trailer_v1->cksum; |
2289 | computed_checksum = update_checksum (startup_header, sizeof (startup_header) + startupfile_blobsize, is_foreign_endianness); |
2307 | computed_checksum = update_checksum (startup_header, sizeof (startup_header) + startupfile_blobsize, is_foreign_endianness); |
2290 | printf (" cksum([0x%zx-0x%zx[) = 0x%08x |
2308 | printf (" cksum([0x%zx-0x%zx[) = 0x%08x - %s\n", startupheader_offset, startuptrailer_offset, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD")); |
2291 | if (computed_checksum != recorded_checksum) |
2309 | if (computed_checksum != recorded_checksum) |
2292 | printf ("Computed cksum: 0x%08x |
2310 | printf ("Computed cksum: 0x%08x\n", computed_checksum); |
2293 | } |
2311 | } |
2294 | 2312 | ||
2295 | 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 |
2313 | 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 |
2296 | } |
2314 | } |
2297 | 2315 | ||
Line 2482... | Line 2500... | ||
2482 | sprintf (&recorded_sha512[2 * byte_index], "%02x", image_trailer_v2->sha512[byte_index]); |
2500 | sprintf (&recorded_sha512[2 * byte_index], "%02x", image_trailer_v2->sha512[byte_index]); |
2483 | strcpy (computed_sha512, SHA512 (image_header, imagetrailer_offset - imageheader_offset, NULL)); |
2501 | strcpy (computed_sha512, SHA512 (image_header, imagetrailer_offset - imageheader_offset, NULL)); |
2484 | recorded_checksum = image_trailer_v2->cksum; |
2502 | recorded_checksum = image_trailer_v2->cksum; |
2485 | computed_checksum = update_checksum (image_header, imagetrailer_offset + SHA512_DIGEST_LENGTH - imageheader_offset, is_foreign_endianness); |
2503 | computed_checksum = update_checksum (image_header, imagetrailer_offset + SHA512_DIGEST_LENGTH - imageheader_offset, is_foreign_endianness); |
2486 | printf (" sha512([0x%zx-0x%zx[) = %s - %s\n", imageheader_offset, imagetrailer_offset, recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD")); |
2504 | printf (" sha512([0x%zx-0x%zx[) = %s - %s\n", imageheader_offset, imagetrailer_offset, recorded_sha512, (strcasecmp (computed_sha512, recorded_sha512) == 0 ? "GOOD" : "BAD")); |
2487 | printf (" cksum([0x%zx-0x%zx[) = 0x%08x |
2505 | printf (" cksum([0x%zx-0x%zx[) = 0x%08x - %s\n", imageheader_offset, imagetrailer_offset + SHA512_DIGEST_LENGTH, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD")); |
2488 | if (strcasecmp (computed_sha512, recorded_sha512) != 0) |
2506 | if (strcasecmp (computed_sha512, recorded_sha512) != 0) |
2489 | printf ("Computed SHA-512: %s\n", computed_sha512); |
2507 | printf ("Computed SHA-512: %s\n", computed_sha512); |
2490 | if (computed_checksum != recorded_checksum) |
2508 | if (computed_checksum != recorded_checksum) |
2491 | printf ("Computed cksum: 0x%08x |
2509 | printf ("Computed cksum: 0x%08x\n", computed_checksum); |
2492 | } |
2510 | } |
2493 | else // old v1 trailer |
2511 | else // old v1 trailer |
2494 | { |
2512 | { |
2495 | recorded_checksum = image_trailer_v1->cksum; |
2513 | recorded_checksum = image_trailer_v1->cksum; |
2496 | computed_checksum = update_checksum (image_header, image_header->image_size - sizeof (image_trailer_v1_t), is_foreign_endianness); |
2514 | computed_checksum = update_checksum (image_header, image_header->image_size - sizeof (image_trailer_v1_t), is_foreign_endianness); |
2497 | printf (" cksum([0x%zx-0x%zx[) = 0x%08x |
2515 | printf (" cksum([0x%zx-0x%zx[) = 0x%08x - %s\n", imageheader_offset, imagetrailer_offset, recorded_checksum, (computed_checksum == recorded_checksum ? "GOOD" : "BAD")); |
2498 | if (computed_checksum != recorded_checksum) |
2516 | if (computed_checksum != recorded_checksum) |
2499 | printf ("Computed cksum: 0x%08x |
2517 | printf ("Computed cksum: 0x%08x\n", computed_checksum); |
2500 | } |
2518 | } |
2501 | 2519 | ||
2502 | current_offset += (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)); // now reach the next segment (typically end of file) |
2520 | current_offset += (image_header->flags & IMAGE_FLAGS_TRAILER_V2 ? sizeof (image_trailer_v2_t) : sizeof (image_trailer_v1_t)); // now reach the next segment (typically end of file) |
2503 | } |
2521 | } |
2504 | 2522 |