VirtualBox

source: vbox/trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp@ 58806

Last change on this file since 58806 was 58806, checked in by vboxsync, 9 years ago

bs3kit: Unfinished work -> home.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.2 KB
Line 
1/* $Id: VBoxBs3ObjConverter.cpp 58806 2015-11-20 20:02:34Z vboxsync $ */
2/** @file
3 * VirtualBox Validation Kit - Boot Sector 3 object file convert.
4 */
5
6/*
7 * Copyright (C) 2006-2015 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27
28/*********************************************************************************************************************************
29* Header Files *
30*********************************************************************************************************************************/
31#include <stdio.h>
32#include <string.h>
33#include <stdlib.h>
34#include <errno.h>
35#include <iprt/types.h>
36#include <iprt/assert.h>
37
38#include <iprt/formats/elf64.h>
39#include <iprt/formats/elf-amd64.h>
40#include <iprt/formats/pecoff.h>
41
42
43/*********************************************************************************************************************************
44* Defined Constants And Macros *
45*********************************************************************************************************************************/
46#if ARCH_BITS == 64 && !defined(RT_OS_WINDOWS)
47# define ELF_FMT_X64 "lx"
48# define ELF_FMT_D64 "ld"
49#else
50# define ELF_FMT_X64 "llx"
51# define ELF_FMT_D64 "lld"
52#endif
53
54
55/*********************************************************************************************************************************
56* Global Variables *
57*********************************************************************************************************************************/
58/** Verbosity level. */
59static unsigned g_cVerbose = 0;
60
61
62/**
63 * Opens a file for binary reading or writing.
64 *
65 * @returns File stream handle.
66 * @param pszFile The name of the file.
67 * @param fWrite Whether to open for writing or reading.
68 */
69static FILE *openfile(const char *pszFile, bool fWrite)
70{
71#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
72 FILE *pFile = fopen(pszFile, fWrite ? "wb" : "rb");
73#else
74 FILE *pFile = fopen(pszFile, fWrite ? "w" : "r");
75#endif
76 if (!pFile)
77 fprintf(stderr, "error: Failed to open '%s' for %s: %s (%d)\n",
78 pszFile, fWrite ? "writing" : "reading", strerror(errno), errno);
79 return pFile;
80}
81
82
83/**
84 * Read the given file into memory.
85 *
86 * @returns true on success, false on failure.
87 * @param pszFile The file to read.
88 * @param ppvFile Where to return the memory.
89 * @param pcbFile Where to return the size.
90 */
91static bool readfile(const char *pszFile, void **ppvFile, size_t *pcbFile)
92{
93 FILE *pFile = openfile(pszFile, false);
94 if (pFile)
95 {
96 /*
97 * Figure the size.
98 */
99 if (fseek(pFile, 0, SEEK_END) == 0)
100 {
101 long cbFile = ftell(pFile);
102 if (cbFile > 0)
103 {
104 if (fseek(pFile, SEEK_SET, 0) == 0)
105 {
106 /*
107 * Allocate and read content.
108 */
109 void *pvFile = malloc((size_t)cbFile);
110 if (pvFile)
111 {
112 if (fread(pvFile, cbFile, 1, pFile) == 1)
113 {
114 *ppvFile = pvFile;
115 *pcbFile = (size_t)cbFile;
116 fclose(pFile);
117 return true;
118 }
119 free(pvFile);
120 fprintf(stderr, "error: fread failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
121 }
122 else
123 fprintf(stderr, "error: failed to allocate %ld bytes of memory for '%s'\n", cbFile, pszFile);
124 }
125 else
126 fprintf(stderr, "error: fseek #2 failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
127 }
128 else
129 fprintf(stderr, "error: ftell failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
130 }
131 else
132 fprintf(stderr, "error: fseek #1 failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
133 fclose(pFile);
134 }
135 return false;
136}
137
138
139/**
140 * Write the given file into memory.
141 *
142 * @returns true on success, false on failure.
143 * @param pszFile The file to write.
144 * @param pvFile Where to return the memory.
145 * @param cbFile Where to return the size.
146 */
147static bool writefile(const char *pszFile, void const *pvFile, size_t cbFile)
148{
149 remove(pszFile);
150
151 int rc = -1;
152 FILE *pFile = openfile(pszFile, true);
153 if (pFile)
154 {
155 if (fwrite(pvFile, cbFile, 1, pFile) == 1)
156 {
157 fclose(pFile);
158 return true;
159 }
160 fprintf(stderr, "error: fwrite failed in '%s': %s (%d)\n", pszFile, strerror(errno), errno);
161 fclose(pFile);
162 }
163 return false;
164}
165
166
167/**
168 * Reports an error and returns false.
169 *
170 * @returns false
171 * @param pszFile The filename.
172 * @param pszFormat The message format string.
173 * @param ... Format arguments.
174 */
175static bool error(const char *pszFile, const char *pszFormat, ...)
176{
177 fprintf(stderr, "error: %s: ", pszFile);
178 va_list va;
179 va_start(va, pszFormat);
180 vfprintf(stderr, pszFormat, va);
181 va_end(va);
182 return false;
183}
184
185
186/** AMD64 relocation type names for ELF. */
187static const char * const g_apszElfAmd64RelTypes[] =
188{
189 "R_X86_64_NONE",
190 "R_X86_64_64",
191 "R_X86_64_PC32",
192 "R_X86_64_GOT32",
193 "R_X86_64_PLT32",
194 "R_X86_64_COPY",
195 "R_X86_64_GLOB_DAT",
196 "R_X86_64_JMP_SLOT",
197 "R_X86_64_RELATIVE",
198 "R_X86_64_GOTPCREL",
199 "R_X86_64_32",
200 "R_X86_64_32S",
201 "R_X86_64_16",
202 "R_X86_64_PC16",
203 "R_X86_64_8",
204 "R_X86_64_PC8",
205 "R_X86_64_DTPMOD64",
206 "R_X86_64_DTPOFF64",
207 "R_X86_64_TPOFF64",
208 "R_X86_64_TLSGD",
209 "R_X86_64_TLSLD",
210 "R_X86_64_DTPOFF32",
211 "R_X86_64_GOTTPOFF",
212 "R_X86_64_TPOFF32",
213};
214
215
216static bool convertelf(const char *pszFile, uint8_t *pbFile, size_t cbFile)
217{
218 /*
219 * Validate the header and our other expectations.
220 */
221 Elf64_Ehdr const *pEhdr = (Elf64_Ehdr const *)pbFile;
222 if ( pEhdr->e_ident[EI_CLASS] != ELFCLASS64
223 || pEhdr->e_ident[EI_DATA] != ELFDATA2LSB
224 || pEhdr->e_ehsize != sizeof(Elf64_Ehdr)
225 || pEhdr->e_shentsize != sizeof(Elf64_Shdr)
226 || pEhdr->e_version != EV_CURRENT )
227 return error(pszFile, "Unsupported ELF config\n");
228 if (pEhdr->e_type != ET_REL)
229 return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_type);
230 if (pEhdr->e_machine != EM_X86_64)
231 return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_machine);
232 if (pEhdr->e_phnum != 0)
233 return error(pszFile, "Expected e_phnum to be zero not %u\n", pEhdr->e_phnum);
234 if (pEhdr->e_shnum < 2)
235 return error(pszFile, "Expected e_shnum to be two or higher\n");
236 if (pEhdr->e_shstrndx >= pEhdr->e_shnum || pEhdr->e_shstrndx == 0)
237 return error(pszFile, "Bad e_shstrndx=%u (e_shnum=%u)\n", pEhdr->e_shstrndx, pEhdr->e_shnum);
238 if ( pEhdr->e_shoff >= cbFile
239 || pEhdr->e_shoff + pEhdr->e_shnum * sizeof(Elf64_Shdr) > cbFile)
240 return error(pszFile, "Section table is outside the file (e_shoff=%#llx, e_shnum=%u, cbFile=%#llx)\n",
241 pEhdr->e_shstrndx, pEhdr->e_shnum, (uint64_t)cbFile);
242
243 /*
244 * Locate the section name string table.
245 * We assume it's okay as we only reference it in verbose mode.
246 */
247 Elf64_Shdr const *paShdrs = (Elf64_Shdr const *)&pbFile[pEhdr->e_shoff];
248 const char * pszStrTab = (const char *)&pbFile[paShdrs[pEhdr->e_shstrndx].sh_offset];
249
250 /*
251 * Work the section table.
252 */
253 for (uint32_t i = 1; i < pEhdr->e_shnum; i++)
254 {
255 if (g_cVerbose)
256 printf("shdr[%u]: name=%#x '%s' type=%#x flags=%#" ELF_FMT_X64 " addr=%#" ELF_FMT_X64 " off=%#" ELF_FMT_X64 " size=%#" ELF_FMT_X64 "\n"
257 " link=%u info=%#x align=%#" ELF_FMT_X64 " entsize=%#" ELF_FMT_X64 "\n",
258 i, paShdrs[i].sh_name, &pszStrTab[paShdrs[i].sh_name], paShdrs[i].sh_type, paShdrs[i].sh_flags,
259 paShdrs[i].sh_addr, paShdrs[i].sh_offset, paShdrs[i].sh_size,
260 paShdrs[i].sh_link, paShdrs[i].sh_info, paShdrs[i].sh_addralign, paShdrs[i].sh_entsize);
261 if (paShdrs[i].sh_type == SHT_RELA)
262 {
263 if (paShdrs[i].sh_entsize != sizeof(Elf64_Rela))
264 return error(pszFile, "Expected sh_entsize to be %u not %u for section #%u (%s)\n", (unsigned)sizeof(Elf64_Rela),
265 paShdrs[i].sh_entsize, i, &pszStrTab[paShdrs[i].sh_name]);
266 uint32_t const cRelocs = paShdrs[i].sh_size / sizeof(Elf64_Rela);
267 if (cRelocs * sizeof(Elf64_Rela) != paShdrs[i].sh_size)
268 return error(pszFile, "Uneven relocation entry count in #%u (%s): sh_size=%#" ELF_FMT_X64 "\n", (unsigned)sizeof(Elf64_Rela),
269 paShdrs[i].sh_entsize, i, &pszStrTab[paShdrs[i].sh_name], paShdrs[i].sh_size);
270 if ( paShdrs[i].sh_offset > cbFile
271 || paShdrs[i].sh_size >= cbFile
272 || paShdrs[i].sh_offset + paShdrs[i].sh_size > cbFile)
273 return error(pszFile, "The content of section #%u '%s' is outside the file (%#" ELF_FMT_X64 " LB %#" ELF_FMT_X64 ", cbFile=%#lx)\n",
274 i, &pszStrTab[paShdrs[i].sh_name], paShdrs[i].sh_offset, paShdrs[i].sh_size, (unsigned long)cbFile);
275 Elf64_Rela *paRels = (Elf64_Rela *)&pbFile[paShdrs[i].sh_offset];
276 for (uint32_t j = 0; j < cRelocs; j++)
277 {
278 uint8_t const bType = ELF64_R_TYPE(paRels[j].r_info);
279 if (g_cVerbose > 1)
280 printf("%#018" ELF_FMT_X64 " %#018" ELF_FMT_X64 " %s %+" ELF_FMT_D64 "\n", paRels[j].r_offset, paRels[j].r_info,
281 bType < RT_ELEMENTS(g_apszElfAmd64RelTypes) ? g_apszElfAmd64RelTypes[bType] : "unknown", paRels[j].r_addend);
282
283 /* Truncate 64-bit wide absolute relocations, ASSUMING that the high bits
284 are already zero and won't be non-zero after calculating the fixup value. */
285 if (bType == R_X86_64_64)
286 {
287 paRels[j].r_info &= ~(uint64_t)0xff;
288 paRels[j].r_info |= R_X86_64_32;
289 }
290 }
291 }
292 else if (paShdrs[i].sh_type == SHT_REL)
293 return error(pszFile, "Did not expect SHT_REL sections (#%u '%s')\n", i, &pszStrTab[paShdrs[i].sh_name]);
294 }
295 return true;
296}
297
298
299/** AMD64 relocation type names for (Microsoft) COFF. */
300static const char * const g_apszCoffAmd64RelTypes[] =
301{
302 "ABSOLUTE",
303 "ADDR64",
304 "ADDR32",
305 "ADDR32NB",
306 "REL32",
307 "REL32_1",
308 "REL32_2",
309 "REL32_3",
310 "REL32_4",
311 "REL32_5",
312 "SECTION",
313 "SECREL",
314 "SECREL7",
315 "TOKEN",
316 "SREL32",
317 "PAIR",
318 "SSPAN32"
319};
320
321static bool convertcoff(const char *pszFile, uint8_t *pbFile, size_t cbFile)
322{
323 /*
324 * Validate the header and our other expectations.
325 */
326 PIMAGE_FILE_HEADER pHdr = (PIMAGE_FILE_HEADER)pbFile;
327 if (pHdr->Machine != IMAGE_FILE_MACHINE_AMD64)
328 return error(pszFile, "Expected IMAGE_FILE_MACHINE_AMD64 not %#x\n", pHdr->Machine);
329 if (pHdr->SizeOfOptionalHeader != 0)
330 return error(pszFile, "Expected SizeOfOptionalHeader to be zero, not %#x\n", pHdr->SizeOfOptionalHeader);
331 if (pHdr->NumberOfSections == 0)
332 return error(pszFile, "Expected NumberOfSections to be non-zero\n");
333 uint32_t const cbHeaders = pHdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) + sizeof(*pHdr);
334 if (cbHeaders > cbFile)
335 return error(pszFile, "Section table goes beyond the end of the of the file (cSections=%#x)\n", pHdr->NumberOfSections);
336 if (pHdr->NumberOfSymbols)
337 {
338 if ( pHdr->PointerToSymbolTable >= cbFile
339 || pHdr->NumberOfSymbols * (uint64_t)IMAGE_SIZE_OF_SYMBOL > cbFile)
340 return error(pszFile, "Symbol table goes beyond the end of the of the file (cSyms=%#x, offFile=%#x)\n",
341 pHdr->NumberOfSymbols, pHdr->PointerToSymbolTable);
342 }
343
344 /* Switch it to a x86 machine. */
345 pHdr->Machine = IMAGE_FILE_MACHINE_I386;
346
347 /*
348 * Work the section table.
349 */
350 PCIMAGE_SECTION_HEADER paShdrs = (PCIMAGE_SECTION_HEADER)(pHdr + 1);
351 for (uint32_t i = 0; i < pHdr->NumberOfSections; i++)
352 {
353 if (g_cVerbose)
354 printf("shdr[%2u]: rva=%#010x cbVirt=%#010x '%-8.8s'\n"
355 " offFile=%#010x cbFile=%#010x\n"
356 " offRelocs=%#010x cRelocs=%#010x\n"
357 " offLines=%#010x cLines=%#010x Characteristics=%#010x\n",
358 i, paShdrs[i].VirtualAddress, paShdrs[i].Misc.VirtualSize, paShdrs[i].Name,
359 paShdrs[i].PointerToRawData, paShdrs[i].SizeOfRawData,
360 paShdrs[i].PointerToRelocations, paShdrs[i].NumberOfRelocations,
361 paShdrs[i].PointerToLinenumbers, paShdrs[i].NumberOfLinenumbers, paShdrs[i].Characteristics);
362 uint32_t const cRelocs = paShdrs[i].NumberOfRelocations;
363 if (cRelocs > 0)
364 {
365 if ( paShdrs[i].PointerToRelocations < cbHeaders
366 || paShdrs[i].PointerToRelocations >= cbFile
367 || paShdrs[i].PointerToRelocations + cRelocs * sizeof(IMAGE_RELOCATION) > cbFile)
368 return error(pszFile, "Relocation beyond the end of the file or overlapping the headers (section #%u)\n", i);
369
370 uint32_t const cbRawData = paShdrs[i].SizeOfRawData;
371 if ( paShdrs[i].PointerToRawData < cbHeaders
372 || paShdrs[i].PointerToRawData >= cbFile
373 || paShdrs[i].PointerToRawData + cbRawData > cbFile)
374 return error(pszFile, "Raw data beyond the end of the file or overlapping the headers (section #%u)\n", i);
375 uint8_t *pbRawData = &pbFile[paShdrs[i].PointerToRawData];
376
377 /*
378 * Convert from AMD64 fixups to I386 ones, assuming 64-bit addresses
379 * being fixed up doesn't need the high dword and that it's
380 * appropriately initialized already.
381 */
382 PIMAGE_RELOCATION paRelocs = (PIMAGE_RELOCATION)&pbFile[paShdrs[i].PointerToRelocations];
383 for (uint32_t j = 0; j < cRelocs; j++)
384 {
385 RTPTRUNION uLoc;
386 uLoc.pu8 = paRelocs[j].u.VirtualAddress < cbRawData ? &pbRawData[paRelocs[j].u.VirtualAddress] : NULL;
387
388 /* Print it. */
389 if (g_cVerbose > 1)
390 {
391 size_t off = printf("%#010x %#010x", paRelocs[j].u.VirtualAddress, paRelocs[j].SymbolTableIndex);
392 switch (paRelocs[j].Type)
393 {
394 case IMAGE_REL_AMD64_ADDR64:
395 if (uLoc.pu64)
396 off += printf(" %#018" ELF_FMT_X64 "", *uLoc.pu64);
397 break;
398 case IMAGE_REL_AMD64_ADDR32:
399 case IMAGE_REL_AMD64_ADDR32NB:
400 case IMAGE_REL_AMD64_REL32:
401 case IMAGE_REL_AMD64_REL32_1:
402 case IMAGE_REL_AMD64_REL32_2:
403 case IMAGE_REL_AMD64_REL32_3:
404 case IMAGE_REL_AMD64_REL32_4:
405 case IMAGE_REL_AMD64_REL32_5:
406 case IMAGE_REL_AMD64_SECREL:
407 if (uLoc.pu32)
408 off += printf(" %#010x", *uLoc.pu32);
409 break;
410 case IMAGE_REL_AMD64_SECTION:
411 if (uLoc.pu16)
412 off += printf(" %#06x", *uLoc.pu16);
413 break;
414 case IMAGE_REL_AMD64_SECREL7:
415 if (uLoc.pu8)
416 off += printf(" %#04x", *uLoc.pu8);
417 break;
418 }
419 while (off < 36)
420 off += printf(" ");
421 printf(" %s\n",
422 paRelocs[j].Type < RT_ELEMENTS(g_apszCoffAmd64RelTypes)
423 ? g_apszCoffAmd64RelTypes[paRelocs[j].Type] : "unknown");
424 }
425
426 /* Convert it. */
427 switch (paRelocs[j].Type)
428 {
429 case IMAGE_REL_AMD64_ADDR64:
430 {
431 uint64_t uAddend = 0;
432 if (uLoc.pu64)
433 {
434 if (paRelocs[j].u.VirtualAddress + 8 > cbRawData)
435 return error(pszFile, "ADDR64 at %#x in section %u '%-8.8s' not fully in raw data\n",
436 paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name);
437 uAddend = *uLoc.pu64;
438 }
439 if (uAddend > _1G)
440 return error(pszFile, "ADDR64 with large addend (%#llx) at %#x in section %u '%-8.8s'\n",
441 uAddend, paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name);
442 paRelocs[j].Type = IMAGE_REL_I386_DIR32;
443 break;
444 }
445
446 case IMAGE_REL_AMD64_REL32_1:
447 case IMAGE_REL_AMD64_REL32_2:
448 case IMAGE_REL_AMD64_REL32_3:
449 case IMAGE_REL_AMD64_REL32_4:
450 case IMAGE_REL_AMD64_REL32_5:
451 {
452 if (paRelocs[j].u.VirtualAddress + 4 > cbRawData)
453 return error(pszFile, "%s at %#x in section %u '%-8.8s' is not (fully) in raw data\n",
454 g_apszCoffAmd64RelTypes[paRelocs[j].Type], paRelocs[j].u.VirtualAddress, i,
455 paShdrs[i].Name);
456 *uLoc.pu32 += paRelocs[j].Type - IMAGE_REL_AMD64_REL32;
457 paRelocs[j].Type = IMAGE_REL_I386_REL32;
458 break;
459 }
460
461 /* These are 1:1 conversions: */
462 case IMAGE_REL_AMD64_ADDR32:
463 paRelocs[j].Type = IMAGE_REL_I386_DIR32;
464 break;
465 case IMAGE_REL_AMD64_ADDR32NB:
466 paRelocs[j].Type = IMAGE_REL_I386_DIR32NB;
467 break;
468 case IMAGE_REL_AMD64_REL32:
469 paRelocs[j].Type = IMAGE_REL_I386_REL32;
470 break;
471 case IMAGE_REL_AMD64_SECTION:
472 paRelocs[j].Type = IMAGE_REL_I386_SECTION;
473 break;
474 case IMAGE_REL_AMD64_SECREL:
475 paRelocs[j].Type = IMAGE_REL_I386_SECREL;
476 break;
477 case IMAGE_REL_AMD64_SECREL7:
478 paRelocs[j].Type = IMAGE_REL_I386_SECREL7;
479 break;
480 case IMAGE_REL_AMD64_ABSOLUTE: /* no-op for alignment. */
481 paRelocs[j].Type = IMAGE_REL_I386_ABSOLUTE;
482 break;
483
484 default:
485 return error(pszFile, "Unsupported fixup type %#x (%s) at rva=%#x in section #%u '%-8.8'\n",
486 paRelocs[j].Type,
487 paRelocs[j].Type < RT_ELEMENTS(g_apszCoffAmd64RelTypes)
488 ? g_apszCoffAmd64RelTypes[paRelocs[j].Type] : "unknown",
489 paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name);
490 }
491 }
492 }
493 }
494 return true;
495}
496
497
498#define PUBDEF UINT8_C(0x90)
499#define THEADR UINT8_C(0x80)
500#define EXTDEF UINT8_C(0x88)
501#define SEGDEF UINT8_C(0x98)
502#define LNAMES UINT8_C(0x96)
503#define GRPDEF UINT8_C(0x9a)
504#define REC32 UINT8_C(0x01) /**< Flag indicating 32-bit record. */
505
506/**
507 * Renames references to intrinsic helper functions so they won't clash between
508 * 32-bit and 16-bit code.
509 *
510 * @returns true / false.
511 * @param pszFile File name for complaining.
512 * @param pbFile Pointer to the file content.
513 * @param cbFile Size of the file content.
514 */
515static bool convertomf(const char *pszFile, uint8_t *pbFile, size_t cbFile)
516{
517 const char **papchLNames = (const char **)calloc(sizeof(*papchLNames), _64K);
518 uint32_t cLNames = 0;
519 bool fProbably32bit = false;
520 uint32_t off;
521
522 while (off + 3 < cbFile)
523 {
524 uint8_t bRecType = pbFile[off];
525 uint16_t cbRec = RT_MAKE_U16(pbFile[off + 1], pbFile[off + 2]);
526 if (g_cVerbose > 2)
527 printf( "%#07x: type=%#04x len=%#06x\n", off, bRecType, cbRec);
528 if (off + cbRec > cbFile)
529 return error(pszFile, "Invalid record length at %#x: %#x (cbFile=%#lx)\n", off, cbRec, (unsigned long)cbFile);
530
531 if (bRecType & REC32)
532 fProbably32bit = true;
533
534 uint32_t offRec = 0;
535 uint8_t *pbRec = &pbFile[off + 3];
536 switch (bRecType)
537 {
538 /*
539 * Scan external definitions for intrinsics needing mangling.
540 */
541 case EXTDEF:
542 {
543 break;
544 }
545
546 /*
547 * Record LNAME records, scanning for FLAT.
548 */
549 case LNAMES:
550 {
551 while (offRec + 1 < cbRec)
552 {
553 uint8_t cch = *pbRec[offRec];
554 if (offRec + 1 + cch >= cb)
555 {
556 }
557 }
558 break;
559 }
560
561 /*
562 * Display public names if -v is specified.
563 */
564 case PUBDEF:
565 case PUBDEF | REC32:
566 if (g_cVerbose > 0)
567 {
568
569 }
570 break;
571 }
572
573 /* advance */
574 off += cbRec + 3;
575 }
576 return true;
577}
578
579
580/**
581 * Does the convertion using convertelf and convertcoff.
582 *
583 * @returns exit code (0 on success, non-zero on failure)
584 * @param pszFile The file to convert.
585 */
586static int convertit(const char *pszFile)
587{
588 void *pvFile;
589 size_t cbFile;
590 if (readfile(pszFile, &pvFile, &cbFile))
591 {
592 bool fRc = false;
593 uint8_t *pbFile = (uint8_t *)pvFile;
594 if ( cbFile > sizeof(Elf64_Ehdr)
595 && pbFile[0] == ELFMAG0
596 && pbFile[1] == ELFMAG1
597 && pbFile[2] == ELFMAG2
598 && pbFile[3] == ELFMAG3)
599 fRc = convertelf(pszFile, pbFile, cbFile);
600 else if ( cbFile > sizeof(IMAGE_FILE_HEADER)
601 && RT_MAKE_U16(pbFile[0], pbFile[1]) == IMAGE_FILE_MACHINE_AMD64
602 && RT_MAKE_U16(pbFile[2], pbFile[3]) * sizeof(IMAGE_SECTION_HEADER) + sizeof(IMAGE_FILE_HEADER)
603 < cbFile
604 && RT_MAKE_U16(pbFile[2], pbFile[3]) > 0)
605 fRc = convertcoff(pszFile, pbFile, cbFile);
606 else if ( cbFile >= 8
607 && pbFile[0] == THEADR
608 && RT_MAKE_U16(pbFile[1], pbFile[2]) < cbFile)
609 fRc = convertomf(pszFile, pbFile, cbFile);
610 else
611 fprintf(stderr, "error: Don't recognize format of '%s' (%#x %#x %#x %#x, cbFile=%lu)\n",
612 pszFile, pbFile[0], pbFile[1], pbFile[2], pbFile[3], (unsigned long)cbFile);
613 if (fRc)
614 fRc = writefile(pszFile, pvFile, cbFile);
615 free(pvFile);
616 if (fRc)
617 return 0;
618 }
619 return 1;
620}
621
622
623int main(int argc, char **argv)
624{
625 int rcExit = 0;
626
627 /*
628 * Scan the arguments.
629 */
630 for (int i = 1; i < argc; i++)
631 {
632 if (argv[i][0] == '-')
633 {
634 const char *pszOpt = &argv[i][1];
635 if (*pszOpt == '-')
636 {
637 /* Convert long options to short ones. */
638 pszOpt--;
639 if (!strcmp(pszOpt, "--verbose"))
640 pszOpt = "v";
641 else if (!strcmp(pszOpt, "--version"))
642 pszOpt = "V";
643 else if (!strcmp(pszOpt, "--help"))
644 pszOpt = "h";
645 else
646 {
647 fprintf(stderr, "syntax errro: Unknown options '%s'\n", pszOpt);
648 return 2;
649 }
650 }
651
652 /* Process the list of short options. */
653 while (*pszOpt)
654 {
655 switch (*pszOpt++)
656 {
657 case 'v':
658 g_cVerbose++;
659 break;
660
661 case 'V':
662 printf("%s\n", "$Revision: 58806 $");
663 return 0;
664
665 case '?':
666 case 'h':
667 printf("usage: %s [options] -o <output> <input1> [input2 ... [inputN]]\n",
668 argv[0]);
669 return 0;
670 }
671 }
672 }
673 else
674 {
675 /*
676 * File to convert. Do the job right away.
677 */
678 rcExit = convertit(argv[i]);
679 if (rcExit != 0)
680 break;
681 }
682 }
683
684 return rcExit;
685}
686
687
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette