Changeset 59932 in vbox
- Timestamp:
- Mar 4, 2016 4:01:18 PM (9 years ago)
- Location:
- trunk/src/VBox/ValidationKit/bootsectors
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/bootsectors/Config.kmk
r59863 r59932 118 118 TOOL_Bs3Gcc64Elf64_COMPILE_C_DEPEND = $(VBoxBs3ObjConverter_1_TARGET) 119 119 TOOL_Bs3Gcc64Elf64_COMPILE_C_DEPORD = 120 TOOL_Bs3Gcc64Elf64_COMPILE_C_OUTPUT = 120 TOOL_Bs3Gcc64Elf64_COMPILE_C_OUTPUT = $(obj).orignal 121 121 define TOOL_Bs3Gcc64Elf64_COMPILE_C_CMDS 122 122 $(QUIET)$(TOOL_Bs3Gcc64Elf64_CC) -c\ … … 139 139 TOOL_Bs3Gcc64Elf64_COMPILE_CXX_DEPEND = $(VBoxBs3ObjConverter_1_TARGET) 140 140 TOOL_Bs3Gcc64Elf64_COMPILE_CXX_DEPORD = 141 TOOL_Bs3Gcc64Elf64_COMPILE_CXX_OUTPUT = 141 TOOL_Bs3Gcc64Elf64_COMPILE_CXX_OUTPUT = $(obj).orignal 142 142 define TOOL_Bs3Gcc64Elf64_COMPILE_CXX_CMDS 143 143 $(QUIET)$(TOOL_Bs3Gcc64Elf64_CXX) -c\ … … 157 157 TOOL_Bs3Vcc64_CXX = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_CXX) 158 158 TOOL_Bs3Vcc64_COBJSUFF = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COBJSUFF) 159 TOOL_Bs3Vcc64_CFLAGS = $(filter-out -TC,$(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_CFLAGS)) -TP # compile as C++159 TOOL_Bs3Vcc64_CFLAGS = $(filter-out -TC,$(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_CFLAGS)) 160 160 TOOL_Bs3Vcc64_CFLAGS.debug = 161 161 TOOL_Bs3Vcc64_CFLAGS.dbgopt = -O1 … … 166 166 TOOL_Bs3Vcc64_COMPILE_C_DEPEND = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_C_DEPEND) $(VBoxBs3ObjConverter_1_TARGET) 167 167 TOOL_Bs3Vcc64_COMPILE_C_DEPORD = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_C_DEPORD) 168 TOOL_Bs3Vcc64_COMPILE_C_OUTPUT = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_C_OUTPUT) 168 TOOL_Bs3Vcc64_COMPILE_C_OUTPUT = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_C_OUTPUT) $(obj).orignal 169 169 TOOL_Bs3Vcc64_COMPILE_C_OUTPUT_MAYBE = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_C_OUTPUT_MAYBE) 170 170 define TOOL_Bs3Vcc64_COMPILE_C_CMDS … … 183 183 TOOL_Bs3Vcc64_COMPILE_CXX_DEPEND = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_CXX_DEPEND) $(VBoxBs3ObjConverter_1_TARGET) 184 184 TOOL_Bs3Vcc64_COMPILE_CXX_DEPORD = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_CXX_DEPORD) 185 TOOL_Bs3Vcc64_COMPILE_CXX_OUTPUT = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_CXX_OUTPUT) 185 TOOL_Bs3Vcc64_COMPILE_CXX_OUTPUT = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_CXX_OUTPUT) $(obj).orignal 186 186 TOOL_Bs3Vcc64_COMPILE_CXX_OUTPUT_MAYBE = $(TOOL_$(VBOX_VCC_TOOL_STEM)AMD64_COMPILE_CXX_OUTPUT_MAYBE) 187 187 define TOOL_Bs3Vcc64_COMPILE_CXX_CMDS … … 212 212 TOOL_Bs3Ow32_COMPILE_C_DEPEND = $(TOOL_OPENWATCOM_COMPILE_C_DEPEND) $(VBoxBs3ObjConverter_1_TARGET) 213 213 TOOL_Bs3Ow32_COMPILE_C_DEPORD = $(TOOL_OPENWATCOM_COMPILE_C_DEPORD) 214 TOOL_Bs3Ow32_COMPILE_C_OUTPUT = $(TOOL_OPENWATCOM_COMPILE_C_OUTPUT) 214 TOOL_Bs3Ow32_COMPILE_C_OUTPUT = $(TOOL_OPENWATCOM_COMPILE_C_OUTPUT) $(obj).orignal 215 215 TOOL_Bs3Ow32_COMPILE_C_OUTPUT_MAYBE = $(TOOL_OPENWATCOM_COMPILE_C_OUTPUT_MAYBE) 216 216 define TOOL_Bs3Ow32_COMPILE_C_CMDS … … 230 230 TOOL_Bs3Ow32_COMPILE_CXX_DEPEND = $(TOOL_OPENWATCOM_COMPILE_CXX_DEPEND) $(VBoxBs3ObjConverter_1_TARGET) 231 231 TOOL_Bs3Ow32_COMPILE_CXX_DEPORD = $(TOOL_OPENWATCOM_COMPILE_CXX_DEPORD) 232 TOOL_Bs3Ow32_COMPILE_CXX_OUTPUT = $(TOOL_OPENWATCOM_COMPILE_CXX_OUTPUT) 232 TOOL_Bs3Ow32_COMPILE_CXX_OUTPUT = $(TOOL_OPENWATCOM_COMPILE_CXX_OUTPUT) $(obj).orignal 233 233 TOOL_Bs3Ow32_COMPILE_CXX_OUTPUT_MAYBE = $(TOOL_OPENWATCOM_COMPILE_CXX_OUTPUT_MAYBE) 234 234 define TOOL_Bs3Ow32_COMPILE_CXX_CMDS … … 390 390 segment BS3DATA32_DATA \ 391 391 segment DATA32 \ 392 segment BS3DATA64 \ 393 segment DATA64 \ 394 segment .data \ 395 segment DATA64_END \ 392 396 clname BS3CODE32 \ 393 397 segment BS3TEXT32 \ 394 398 segment TEXT32 \ 395 clname CODE\399 clname BS3CODE64 \ 396 400 segment BS3TEXT64 \ 397 401 segment TEXT64 \ 398 402 segment .text \ 399 403 segment .rdata \ 400 clname DATA \401 segment BS3DATA64 \402 segment DATA64 \403 segment .data \404 segment .pdata \405 segment .xdata \406 404 407 405 TEMPLATE_VBoxBS3KitImg_DEPS = \ -
trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp
r59902 r59932 34 34 #include <errno.h> 35 35 #include <iprt/types.h> 36 #include <iprt/ctype.h> 36 37 #include <iprt/assert.h> 37 38 #include <iprt/x86.h> … … 40 41 #include <iprt/formats/elf-amd64.h> 41 42 #include <iprt/formats/pecoff.h> 43 #include <iprt/formats/omf.h> 42 44 43 45 … … 176 178 static bool error(const char *pszFile, const char *pszFormat, ...) 177 179 { 180 fflush(stdout); 178 181 fprintf(stderr, "error: %s: ", pszFile); 179 182 va_list va; … … 184 187 } 185 188 189 190 191 /********************************************************************************************************************************* 192 * Common OMF Writer * 193 *********************************************************************************************************************************/ 194 195 /** Entry for each segment/section in the source format for mapping it to a 196 * segment defintion. */ 197 typedef struct OMFTOSEGDEF 198 { 199 /** The segment defintion index of the section, UINT16_MAX if not translated. */ 200 uint16_t iSegDef; 201 /** The group index for this segment, UINT16_MAX if not applicable. */ 202 uint16_t iGrpDef; 203 /** The class name table entry, UINT16_MAX if not applicable. */ 204 uint16_t iClassNm; 205 /** The group name for this segment, UINT16_MAX if not applicable. */ 206 uint16_t iGrpNm; 207 /** The group name for this segment, UINT16_MAX if not applicable. */ 208 uint16_t iSegNm; 209 /** The number of public definitions for this segment. */ 210 uint32_t cPubDefs; 211 /** The segment name (OMF). */ 212 char *pszName; 213 } OMFTOSEGDEF; 214 /** Pointer to a segment/section to segdef mapping. */ 215 typedef OMFTOSEGDEF *POMFTOSEGDEF; 216 217 /** Symbol table translation type. */ 218 typedef enum OMFSYMTYPE 219 { 220 /** Invalid symbol table entry (aux sym). */ 221 OMFSYMTYPE_INVALID = 0, 222 /** Ignored. */ 223 OMFSYMTYPE_IGNORED, 224 /** A public defintion. */ 225 OMFSYMTYPE_PUBDEF, 226 /** An external definition. */ 227 OMFSYMTYPE_EXTDEF, 228 /** A segment reference for fixups. */ 229 OMFSYMTYPE_SEGDEF, 230 /** Internal symbol that may be used for fixups. */ 231 OMFSYMTYPE_INTERNAL 232 } OMFSYMTYPE; 233 234 /** Symbol table translation. */ 235 typedef struct OMFSYMBOL 236 { 237 /** What this source symbol table entry should be translated into. */ 238 OMFSYMTYPE enmType; 239 /** The OMF table index. UINT16_MAX if not applicable. */ 240 uint16_t idx; 241 /** The OMF segment definition index. */ 242 uint16_t idxSegDef; 243 /** The OMF group definition index. */ 244 uint16_t idxGrpDef; 245 } OMFSYMBOL; 246 /** Pointer to an source symbol table translation entry. */ 247 typedef OMFSYMBOL *POMFSYMBOL; 248 249 /** 250 * OMF converter & writer instance. 251 */ 252 typedef struct OMFWRITER 253 { 254 /** The source file name (for bitching). */ 255 const char *pszSrc; 256 /** The destination output file. */ 257 FILE *pDst; 258 259 /** Number of source segments/sections. */ 260 uint32_t cSegments; 261 /** Pointer to the table mapping from source segments/section to segdefs. */ 262 POMFTOSEGDEF paSegments; 263 264 /** Number of entries in the source symbol table. */ 265 uint32_t cSymbols; 266 /** Pointer to the table mapping from source symbols to OMF stuff. */ 267 POMFSYMBOL paSymbols; 268 269 /** The index of the next list of names entry. */ 270 uint16_t idxNextName; 271 272 /** The current record size. */ 273 uint16_t cbRec; 274 /** The current record type */ 275 uint8_t bType; 276 /** The record data buffer (too large, but whatever). */ 277 uint8_t abData[_1K + 64]; 278 /** Alignment padding. */ 279 uint8_t abAlign[2]; 280 281 /** Current FIXUPP entry. */ 282 uint8_t iFixupp; 283 /** FIXUPP records being prepared for LEDATA currently stashed in abData. 284 * We may have to adjust addend values in the LEDATA when converting to OMF 285 * fixups. */ 286 struct 287 { 288 uint16_t cbRec; 289 uint8_t abData[_1K + 64]; 290 uint8_t abAlign[2]; /**< Alignment padding. */ 291 } aFixupps[3]; 292 293 /** The index of the FLAT group. */ 294 uint16_t idxGrpFlat; 295 /** The EXTDEF index of the __ImageBase symbol. */ 296 uint16_t idxExtImageBase; 297 } OMFWRITE; 298 /** Pointer to an OMF writer. */ 299 typedef OMFWRITE *POMFWRITER; 300 301 302 /** 303 * Creates an OMF writer instance. 304 */ 305 static POMFWRITER omfWriter_Create(const char *pszSrc, uint32_t cSegments, uint32_t cSymbols, FILE *pDst) 306 { 307 POMFWRITER pThis = (POMFWRITER)calloc(sizeof(OMFWRITER), 1); 308 if (pThis) 309 { 310 pThis->pszSrc = pszSrc; 311 pThis->idxNextName = 1; /* We start counting at 1. */ 312 pThis->cSegments = cSegments; 313 pThis->paSegments = (POMFTOSEGDEF)calloc(sizeof(OMFTOSEGDEF), cSegments); 314 if (pThis->paSegments) 315 { 316 pThis->cSymbols = cSymbols; 317 pThis->paSymbols = (POMFSYMBOL)calloc(sizeof(OMFSYMBOL), cSymbols); 318 if (pThis->paSymbols) 319 { 320 pThis->pDst = pDst; 321 return pThis; 322 } 323 free(pThis->paSegments); 324 } 325 free(pThis); 326 } 327 error(pszSrc, "Out of memory!\n"); 328 return NULL; 329 } 330 331 /** 332 * Destroys the given OMF writer instance. 333 * @param pThis OMF writer instance. 334 */ 335 static void omfWriter_Destroy(POMFWRITER pThis) 336 { 337 free(pThis->paSymbols); 338 for (uint32_t i = 0; i < pThis->cSegments; i++) 339 if (pThis->paSegments[i].pszName) 340 free(pThis->paSegments[i].pszName); 341 free(pThis->paSegments); 342 free(pThis); 343 } 344 345 static bool omfWriter_RecBegin(POMFWRITER pThis, uint8_t bType) 346 { 347 pThis->bType = bType; 348 pThis->cbRec = 0; 349 return true; 350 } 351 352 static bool omfWriter_RecAddU8(POMFWRITER pThis, uint8_t b) 353 { 354 if (pThis->cbRec < OMF_MAX_RECORD_PAYLOAD) 355 { 356 pThis->abData[pThis->cbRec++] = b; 357 return true; 358 } 359 return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x)!\n", pThis->bType); 360 } 361 362 static bool omfWriter_RecAddU16(POMFWRITER pThis, uint16_t u16) 363 { 364 if (pThis->cbRec + 2 <= OMF_MAX_RECORD_PAYLOAD) 365 { 366 pThis->abData[pThis->cbRec++] = (uint8_t)u16; 367 pThis->abData[pThis->cbRec++] = (uint8_t)(u16 >> 8); 368 return true; 369 } 370 return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x)!\n", pThis->bType); 371 } 372 373 static bool omfWriter_RecAddU32(POMFWRITER pThis, uint32_t u32) 374 { 375 if (pThis->cbRec + 4 <= OMF_MAX_RECORD_PAYLOAD) 376 { 377 pThis->abData[pThis->cbRec++] = (uint8_t)u32; 378 pThis->abData[pThis->cbRec++] = (uint8_t)(u32 >> 8); 379 pThis->abData[pThis->cbRec++] = (uint8_t)(u32 >> 16); 380 pThis->abData[pThis->cbRec++] = (uint8_t)(u32 >> 24); 381 return true; 382 } 383 return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x)!\n", pThis->bType); 384 } 385 386 static bool omfWriter_RecAddIdx(POMFWRITER pThis, uint16_t idx) 387 { 388 if (idx < 128) 389 return omfWriter_RecAddU8(pThis, (uint8_t)idx); 390 if (idx < _32K) 391 return omfWriter_RecAddU8(pThis, (uint8_t)(idx >> 7) | 0x80) 392 && omfWriter_RecAddU8(pThis, (uint8_t)idx); 393 return error(pThis->pszSrc, "Index out of range %#x\n", idx); 394 } 395 396 static bool omfWriter_RecAddBytes(POMFWRITER pThis, const void *pvData, size_t cbData) 397 { 398 if (cbData + pThis->cbRec <= OMF_MAX_RECORD_PAYLOAD) 399 { 400 memcpy(&pThis->abData[pThis->cbRec], pvData, cbData); 401 pThis->cbRec += (uint16_t)cbData; 402 return true; 403 } 404 return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x, cbData=%#x)!\n", pThis->bType, (unsigned)cbData); 405 } 406 407 static bool omfWriter_RecAddStringN(POMFWRITER pThis, const char *pchString, size_t cchString) 408 { 409 if (cchString < 256) 410 { 411 return omfWriter_RecAddU8(pThis, (uint8_t)cchString) 412 && omfWriter_RecAddBytes(pThis, pchString, cchString); 413 } 414 return error(pThis->pszSrc, "String too long (%u bytes): '%*.*s'\n", 415 (unsigned)cchString, (int)cchString, (int)cchString, pchString); 416 } 417 418 static bool omfWriter_RecAddString(POMFWRITER pThis, const char *pszString) 419 { 420 return omfWriter_RecAddStringN(pThis, pszString, strlen(pszString)); 421 } 422 423 static bool omfWriter_RecEnd(POMFWRITER pThis, bool fAddCrc) 424 { 425 if ( !fAddCrc 426 || omfWriter_RecAddU8(pThis, 0)) 427 { 428 OMFRECHDR RecHdr = { pThis->bType, RT_H2LE_U16(pThis->cbRec) }; 429 if ( fwrite(&RecHdr, sizeof(RecHdr), 1, pThis->pDst) == 1 430 && fwrite(pThis->abData, pThis->cbRec, 1, pThis->pDst) == 1) 431 { 432 pThis->bType = 0; 433 pThis->cbRec = 0; 434 return true; 435 } 436 return error(pThis->pszSrc, "Write error\n"); 437 } 438 return false; 439 } 440 441 static bool omfWriter_RecEndWithCrc(POMFWRITER pThis) 442 { 443 return omfWriter_RecEnd(pThis, true /*fAddCrc*/); 444 } 445 446 447 static bool omfWriter_BeginModule(POMFWRITER pThis, const char *pszFile) 448 { 449 return omfWriter_RecBegin(pThis, OMF_THEADR) 450 && omfWriter_RecAddString(pThis, pszFile) 451 && omfWriter_RecEndWithCrc(pThis); 452 } 453 454 static bool omfWriter_LNamesAddN(POMFWRITER pThis, const char *pchName, size_t cchName, uint16_t *pidxName) 455 { 456 /* split? */ 457 if (pThis->cbRec + 1 /*len*/ + cchName + 1 /*crc*/ > OMF_MAX_RECORD_PAYLOAD) 458 { 459 if (pThis->cbRec == 0) 460 return error(pThis->pszSrc, "Too long LNAME '%*.*s'\n", (int)cchName, (int)cchName, pchName); 461 if ( !omfWriter_RecEndWithCrc(pThis) 462 || !omfWriter_RecBegin(pThis, OMF_LNAMES)) 463 return false; 464 } 465 466 if (pidxName) 467 *pidxName = pThis->idxNextName; 468 pThis->idxNextName++; 469 return omfWriter_RecAddStringN(pThis, pchName, cchName); 470 } 471 472 static bool omfWriter_LNamesAdd(POMFWRITER pThis, const char *pszName, uint16_t *pidxName) 473 { 474 return omfWriter_LNamesAddN(pThis, pszName, strlen(pszName), pidxName); 475 } 476 477 static bool omfWriter_LNamesBegin(POMFWRITER pThis) 478 { 479 /* First entry is an empty string. */ 480 return omfWriter_RecBegin(pThis, OMF_LNAMES) 481 && ( pThis->idxNextName > 1 482 || omfWriter_LNamesAddN(pThis, "", 0, NULL)); 483 } 484 485 static bool omfWriter_LNamesEnd(POMFWRITER pThis) 486 { 487 return omfWriter_RecEndWithCrc(pThis); 488 } 489 490 491 static bool omfWriter_SegDef(POMFWRITER pThis, uint8_t bSegAttr, uint32_t cbSeg, uint16_t idxSegName, uint16_t idxSegClass) 492 { 493 return omfWriter_RecBegin(pThis, OMF_SEGDEF32) 494 && omfWriter_RecAddU8(pThis, bSegAttr) 495 && omfWriter_RecAddU32(pThis, cbSeg) 496 && omfWriter_RecAddIdx(pThis, idxSegName) 497 && omfWriter_RecAddIdx(pThis, idxSegClass) 498 && omfWriter_RecAddIdx(pThis, 1) /* overlay name index = NULL entry */ 499 && omfWriter_RecEndWithCrc(pThis); 500 } 501 502 static bool omfWriter_GrpDefBegin(POMFWRITER pThis, uint16_t idxGrpName) 503 { 504 return omfWriter_RecBegin(pThis, OMF_GRPDEF) 505 && omfWriter_RecAddIdx(pThis, idxGrpName); 506 } 507 508 static bool omfWriter_GrpDefAddSegDef(POMFWRITER pThis, uint16_t idxSegDef) 509 { 510 return omfWriter_RecAddU8(pThis, 0xff) 511 && omfWriter_RecAddIdx(pThis, idxSegDef); 512 } 513 514 static bool omfWriter_GrpDefEnd(POMFWRITER pThis) 515 { 516 return omfWriter_RecEndWithCrc(pThis); 517 } 518 519 520 static bool omfWriter_PubDefBegin(POMFWRITER pThis, uint16_t idxGrpDef, uint16_t idxSegDef) 521 { 522 return omfWriter_RecBegin(pThis, OMF_PUBDEF32) 523 && omfWriter_RecAddIdx(pThis, idxGrpDef) 524 && omfWriter_RecAddIdx(pThis, idxSegDef) 525 && ( idxSegDef != 0 526 || omfWriter_RecAddU16(pThis, 0)); 527 528 } 529 530 static bool omfWriter_PubDefAddN(POMFWRITER pThis, uint32_t uValue, const char *pchString, size_t cchString) 531 { 532 /* Split? */ 533 if (pThis->cbRec + 1 + cchString + 4 + 1 + 1 > OMF_MAX_RECORD_PAYLOAD) 534 { 535 if (cchString >= 256) 536 return error(pThis->pszSrc, "PUBDEF string too long %u ('%s')\n", 537 (unsigned)cchString, (int)cchString, (int)cchString, pchString); 538 if (!omfWriter_RecEndWithCrc(pThis)) 539 return false; 540 541 /* Figure out the initial data length. */ 542 pThis->cbRec = 1 + ((pThis->abData[0] & 0x80) != 0); 543 if (pThis->abData[pThis->cbRec] != 0) 544 pThis->cbRec += 1 + ((pThis->abData[pThis->cbRec] & 0x80) != 0); 545 else 546 pThis->cbRec += 3; 547 pThis->bType = OMF_PUBDEF32; 548 } 549 550 return omfWriter_RecAddStringN(pThis, pchString, cchString) 551 && omfWriter_RecAddU32(pThis, uValue) 552 && omfWriter_RecAddIdx(pThis, 0); /* type */ 553 } 554 555 static bool omfWriter_PubDefAdd(POMFWRITER pThis, uint32_t uValue, const char *pszString) 556 { 557 return omfWriter_PubDefAddN(pThis, uValue, pszString, strlen(pszString)); 558 } 559 560 static bool omfWriter_PubDefEnd(POMFWRITER pThis) 561 { 562 return omfWriter_RecEndWithCrc(pThis); 563 } 564 565 /** 566 * EXTDEF - Begin record. 567 */ 568 static bool omfWriter_ExtDefBegin(POMFWRITER pThis) 569 { 570 return omfWriter_RecBegin(pThis, OMF_EXTDEF); 571 572 } 573 574 /** 575 * EXTDEF - Add an entry, split record if necessary. 576 */ 577 static bool omfWriter_ExtDefAddN(POMFWRITER pThis, const char *pchString, size_t cchString) 578 { 579 /* Split? */ 580 if (pThis->cbRec + 1 + cchString + 1 + 1 > OMF_MAX_RECORD_PAYLOAD) 581 { 582 if (cchString >= 256) 583 return error(pThis->pszSrc, "EXTDEF string too long %u ('%s')\n", 584 (unsigned)cchString, (int)cchString, (int)cchString, pchString); 585 if ( !omfWriter_RecEndWithCrc(pThis) 586 || !omfWriter_RecBegin(pThis, OMF_EXTDEF)) 587 return false; 588 } 589 590 return omfWriter_RecAddStringN(pThis, pchString, cchString) 591 && omfWriter_RecAddIdx(pThis, 0); /* type */ 592 } 593 594 /** 595 * EXTDEF - Add an entry, split record if necessary. 596 */ 597 static bool omfWriter_ExtDefAdd(POMFWRITER pThis, const char *pszString) 598 { 599 return omfWriter_ExtDefAddN(pThis, pszString, strlen(pszString)); 600 } 601 602 /** 603 * EXTDEF - End of record. 604 */ 605 static bool omfWriter_ExtDefEnd(POMFWRITER pThis) 606 { 607 return omfWriter_RecEndWithCrc(pThis); 608 } 609 610 /** 611 * COMENT/LINK_PASS_SEP - Add a link pass separator comment. 612 */ 613 static bool omfWriter_LinkPassSeparator(POMFWRITER pThis) 614 { 615 return omfWriter_RecBegin(pThis, OMF_COMENT) 616 && omfWriter_RecAddU8(pThis, OMF_CTYP_NO_LIST) 617 && omfWriter_RecAddU8(pThis, OMF_CCLS_LINK_PASS_SEP) 618 && omfWriter_RecAddU8(pThis, 1) 619 && omfWriter_RecEndWithCrc(pThis); 620 } 621 622 /** 623 * LEDATA + FIXUPP - Begin records. 624 */ 625 static bool omfWriter_LEDataBegin(POMFWRITER pThis, uint16_t idxSeg, uint32_t offSeg, 626 uint32_t cbData, uint32_t cbRawData, void const *pbRawData, uint8_t **ppbData) 627 { 628 if ( omfWriter_RecBegin(pThis, OMF_LEDATA32) 629 && omfWriter_RecAddIdx(pThis, idxSeg) 630 && omfWriter_RecAddU32(pThis, offSeg)) 631 { 632 if ( cbData <= _1K 633 && pThis->cbRec + cbData + 1 <= OMF_MAX_RECORD_PAYLOAD) 634 { 635 uint8_t *pbDst = &pThis->abData[pThis->cbRec]; 636 if (ppbData) 637 *ppbData = pbDst; 638 639 if (cbRawData) 640 memcpy(pbDst, pbRawData, RT_MIN(cbData, cbRawData)); 641 if (cbData > cbRawData) 642 memset(&pbDst[cbRawData], 0, cbData - cbRawData); 643 644 pThis->cbRec += cbData; 645 646 /* Reset the associated FIXUPP records. */ 647 pThis->iFixupp = 0; 648 for (unsigned i = 0; i < RT_ELEMENTS(pThis->aFixupps); i++) 649 pThis->aFixupps[i].cbRec = 0; 650 return true; 651 } 652 error(pThis->pszSrc, "Too much data for LEDATA record! (%#x)\n", (unsigned)cbData); 653 } 654 return false; 655 } 656 657 /** 658 * LEDATA + FIXUPP - Add FIXUPP subrecord bytes, split if necessary. 659 */ 660 static bool omfWriter_LEDataAddFixuppBytes(POMFWRITER pThis, void *pvSubRec, size_t cbSubRec) 661 { 662 /* Split? */ 663 unsigned iFixupp = pThis->iFixupp; 664 if (pThis->aFixupps[iFixupp].cbRec + cbSubRec >= OMF_MAX_RECORD_PAYLOAD) 665 { 666 iFixupp++; 667 if (iFixupp >= RT_ELEMENTS(pThis->aFixupps)) 668 return error(pThis->pszSrc, "Out of FIXUPP records\n"); 669 pThis->iFixupp = iFixupp; 670 pThis->aFixupps[iFixupp].cbRec = 0; /* paranoia */ 671 } 672 673 /* Append the sub-record data. */ 674 memcpy(&pThis->aFixupps[iFixupp].abData[pThis->aFixupps[iFixupp].cbRec], pvSubRec, cbSubRec); 675 pThis->aFixupps[iFixupp].cbRec += (uint16_t)cbSubRec; 676 return true; 677 } 678 679 /** 680 * LEDATA + FIXUPP - Add fixup, split if necessary. 681 */ 682 static bool omfWriter_LEDataAddFixup(POMFWRITER pThis, uint16_t offDataRec, bool fSelfRel, uint8_t bLocation, 683 uint8_t bFrame, uint16_t idxFrame, 684 uint8_t bTarget, uint16_t idxTarget, bool fTargetDisp, uint32_t offTargetDisp) 685 { 686 if (g_cVerbose >= 2) 687 printf("debug: FIXUP[%#x]: off=%#x frame=%u:%#x target=%u:%#x disp=%d:%#x\n", pThis->aFixupps[pThis->iFixupp].cbRec, 688 offDataRec, bFrame, idxFrame, bTarget, idxTarget, fTargetDisp, offTargetDisp); 689 690 if ( offDataRec >= _1K 691 || bFrame >= 6 692 || bTarget > 6 693 || idxFrame >= _32K 694 || idxTarget >= _32K 695 || fTargetDisp != (bTarget <= 4) ) 696 /*return*/ error(pThis->pszSrc, "Internal error: off=%#x frame=%u:%#x target=%u:%#x disp=%d:%#x\n", 697 offDataRec, bFrame, idxFrame, bTarget, idxTarget, fTargetDisp, offTargetDisp); 698 699 /* 700 * Encode the FIXUP subrecord. 701 */ 702 uint8_t abFixup[16]; 703 uint8_t off = 0; 704 /* Location */ 705 abFixup[off++] = (offDataRec >> 8) | (bLocation << 2) | ((uint8_t)!fSelfRel << 6) | 0x80; 706 abFixup[off++] = (uint8_t)offDataRec; 707 /* Fix Data */ 708 abFixup[off++] = 0x00 /*F=0*/ | (bFrame << 4) | 0x00 /*T=0*/ | bTarget; 709 /* Frame Datum */ 710 if (bFrame <= OMF_FIX_F_FRAME_NO) 711 { 712 if (idxFrame >= 128) 713 abFixup[off++] = (uint8_t)(idxFrame >> 8); 714 abFixup[off++] = (uint8_t)idxFrame; 715 } 716 /* Target Datum */ 717 if (idxTarget >= 128) 718 abFixup[off++] = (uint8_t)(idxTarget >> 8); 719 abFixup[off++] = (uint8_t)idxTarget; 720 /* Target Displacement */ 721 if (fTargetDisp) 722 { 723 abFixup[off++] = RT_BYTE1(offTargetDisp); 724 abFixup[off++] = RT_BYTE2(offTargetDisp); 725 abFixup[off++] = RT_BYTE3(offTargetDisp); 726 abFixup[off++] = RT_BYTE4(offTargetDisp); 727 } 728 729 return omfWriter_LEDataAddFixuppBytes(pThis, abFixup, off); 730 } 731 732 /** 733 * LEDATA + FIXUPP - End of records. 734 */ 735 static bool omfWriter_LEDataEnd(POMFWRITER pThis) 736 { 737 if (omfWriter_RecEndWithCrc(pThis)) 738 { 739 for (unsigned iFixupp = 0; iFixupp <= pThis->iFixupp; iFixupp++) 740 { 741 uint8_t const cbRec = pThis->aFixupps[iFixupp].cbRec; 742 if (!cbRec) 743 break; 744 if ( !omfWriter_RecBegin(pThis, OMF_FIXUPP32) 745 || !omfWriter_RecAddBytes(pThis, pThis->aFixupps[iFixupp].abData, cbRec) 746 || !omfWriter_RecEndWithCrc(pThis)) 747 return false; 748 } 749 pThis->iFixupp = 0; 750 return true; 751 } 752 return false; 753 } 754 755 /** 756 * MODEND - End of module, simple variant. 757 */ 758 static bool omfWriter_EndModule(POMFWRITER pThis) 759 { 760 return omfWriter_RecBegin(pThis, OMF_MODEND32) 761 && omfWriter_RecAddU8(pThis, 0) 762 && omfWriter_RecEndWithCrc(pThis); 763 } 764 765 766 767 768 /********************************************************************************************************************************* 769 * ELF64/AMD64 -> ELF64/i386 Converter * 770 *********************************************************************************************************************************/ 186 771 187 772 /** AMD64 relocation type names for ELF. */ … … 298 883 299 884 885 886 887 888 /********************************************************************************************************************************* 889 * COFF -> OMF Converter * 890 *********************************************************************************************************************************/ 891 300 892 /** AMD64 relocation type names for (Microsoft) COFF. */ 301 893 static const char * const g_apszCoffAmd64RelTypes[] = … … 320 912 }; 321 913 322 323 static const char *coffGetSymbolName(PCIMAGE_SYMBOL pSym, const char *pchStrTab, char pszShortName[16]) 914 /** AMD64 relocation type sizes for (Microsoft) COFF. */ 915 static uint8_t const g_acbCoffAmd64RelTypes[] = 916 { 917 8, /* ABSOLUTE */ 918 8, /* ADDR64 */ 919 4, /* ADDR32 */ 920 4, /* ADDR32NB */ 921 4, /* REL32 */ 922 4, /* REL32_1 */ 923 4, /* REL32_2 */ 924 4, /* REL32_3 */ 925 4, /* REL32_4 */ 926 4, /* REL32_5 */ 927 2, /* SECTION */ 928 4, /* SECREL */ 929 1, /* SECREL7 */ 930 0, /* TOKEN */ 931 4, /* SREL32 */ 932 0, /* PAIR */ 933 4, /* SSPAN32 */ 934 }; 935 936 /** Macro for getting the size of a AMD64 COFF relocation. */ 937 #define COFF_AMD64_RELOC_SIZE(a_Type) ( (a_Type) < RT_ELEMENTS(g_acbCoffAmd64RelTypes) ? g_acbCoffAmd64RelTypes[(a_Type)] : 1) 938 939 940 static const char *coffGetSymbolName(PCIMAGE_SYMBOL pSym, const char *pchStrTab, uint32_t cbStrTab, char pszShortName[16]) 324 941 { 325 942 if (pSym->N.Name.Short != 0) … … 329 946 return pszShortName; 330 947 } 331 return pchStrTab + pSym->N.Name.Long; 332 } 333 334 static bool convertcoff(const char *pszFile, uint8_t *pbFile, size_t cbFile) 948 if (pSym->N.Name.Long < cbStrTab) 949 { 950 uint32_t const cbLeft = cbStrTab - pSym->N.Name.Long; 951 const char *pszRet = pchStrTab + pSym->N.Name.Long; 952 if (memchr(pszRet, '\0', cbLeft) != NULL) 953 return pszRet; 954 } 955 error("<null>", "Invalid string table index %#x!\n", pSym->N.Name.Long); 956 return "Invalid Symbol Table Entry"; 957 } 958 959 static bool validateCoff(const char *pszFile, uint8_t const *pbFile, size_t cbFile) 335 960 { 336 961 /* … … 355 980 } 356 981 357 /* Dump the symbol table if verbose mode. */ 358 PIMAGE_SYMBOL paSymTab = (PIMAGE_SYMBOL)&pbFile[pHdr->PointerToSymbolTable]; 359 const char *pchStrTab = (const char *)&paSymTab[pHdr->NumberOfSymbols]; 360 char szShortName[16]; 361 if (g_cVerbose > 2) 362 for (uint32_t i = 0; i < pHdr->NumberOfSymbols; i++) 982 return true; 983 } 984 985 986 static bool convertCoffSectionsToSegDefsAndGrpDefs(POMFWRITER pThis, PCIMAGE_SECTION_HEADER paShdrs, uint16_t cSections) 987 { 988 /* 989 * Do the list of names pass. 990 */ 991 uint16_t idxGrpFlat, idxGrpData; 992 uint16_t idxClassCode, idxClassData, idxClassDebugSymbols, idxClassDebugTypes; 993 if ( !omfWriter_LNamesBegin(pThis) 994 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat) 995 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData) 996 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3CODE64"), &idxClassCode) 997 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FAR_DATA"), &idxClassData) 998 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("DEBSYM"), &idxClassDebugSymbols) 999 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("DEBTYP"), &idxClassDebugTypes) 1000 ) 1001 return false; 1002 1003 bool fHaveData = false; 1004 for (uint16_t i = 0; i < cSections; i++) 1005 { 1006 /* Copy the name and terminate it. */ 1007 char szName[32]; 1008 memcpy(szName, paShdrs[i].Name, sizeof(paShdrs[i].Name)); 1009 unsigned cchName = sizeof(paShdrs[i].Name); 1010 while (cchName > 0 && RT_C_IS_SPACE(szName[cchName - 1])) 1011 cchName--; 1012 if (cchName == 0) 1013 return error(pThis->pszSrc, "Section #%u has an empty name!\n", i); 1014 szName[cchName] = '\0'; 1015 1016 if ( (paShdrs[i].Characteristics & (IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_LNK_INFO)) 1017 || strcmp(szName, ".pdata") == 0 /* Exception stuff, I think, so discard it. */ 1018 || strcmp(szName, ".xdata") == 0 /* Ditto. */ ) 363 1019 { 364 printf("sym[0x%02x]: sect=0x%04x value=0x%08x storageclass=0x%x name=%s\n", 365 i, paSymTab[i].SectionNumber, paSymTab[i].Value, paSymTab[i].StorageClass, 366 coffGetSymbolName(&paSymTab[i], pchStrTab, szShortName)); 367 i += paSymTab[i].NumberOfAuxSymbols; 1020 pThis->paSegments[i].iSegDef = UINT16_MAX; 1021 pThis->paSegments[i].iGrpDef = UINT16_MAX; 1022 pThis->paSegments[i].iSegNm = UINT16_MAX; 1023 pThis->paSegments[i].iGrpNm = UINT16_MAX; 1024 pThis->paSegments[i].iClassNm = UINT16_MAX; 1025 pThis->paSegments[i].pszName = NULL; 368 1026 } 369 370 /* Switch it to a x86 machine. */ 371 pHdr->Machine = IMAGE_FILE_MACHINE_I386; 1027 else 1028 { 1029 /* Translate the name, group and class. */ 1030 if (strcmp(szName, ".text") == 0) 1031 { 1032 strcpy(szName, "BS3TEXT64"); 1033 pThis->paSegments[i].iGrpNm = idxGrpFlat; 1034 pThis->paSegments[i].iClassNm = idxClassCode; 1035 } 1036 else if (strcmp(szName, ".data") == 0) 1037 { 1038 strcpy(szName, "BS3DATA64"); 1039 pThis->paSegments[i].iGrpNm = idxGrpData; 1040 pThis->paSegments[i].iClassNm = idxClassData; 1041 } 1042 else if (strcmp(szName, ".bss") == 0) 1043 { 1044 strcpy(szName, "BS3BSS64"); 1045 pThis->paSegments[i].iGrpNm = idxGrpData; 1046 pThis->paSegments[i].iClassNm = idxClassData; 1047 } 1048 else if (strcmp(szName, ".rdata") == 0) 1049 { 1050 strcpy(szName, "BS3DATA64CONST"); 1051 pThis->paSegments[i].iGrpNm = idxGrpData; 1052 pThis->paSegments[i].iClassNm = idxClassData; 1053 } 1054 else if (strcmp(szName, ".debug$S") == 0) 1055 { 1056 strcpy(szName, "$$SYMBOLS"); 1057 pThis->paSegments[i].iGrpNm = UINT16_MAX; 1058 pThis->paSegments[i].iClassNm = idxClassDebugSymbols; 1059 } 1060 else if (strcmp(szName, ".debug$T") == 0) 1061 { 1062 strcpy(szName, "$$TYPES"); 1063 pThis->paSegments[i].iGrpNm = UINT16_MAX; 1064 pThis->paSegments[i].iClassNm = idxClassDebugTypes; 1065 } 1066 else if (paShdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE)) 1067 { 1068 pThis->paSegments[i].iGrpNm = idxGrpFlat; 1069 pThis->paSegments[i].iClassNm = idxClassCode; 1070 error(pThis->pszSrc, "Unknown code segment: '%s'\n", szName); 1071 } 1072 else 1073 { 1074 pThis->paSegments[i].iGrpNm = idxGrpData; 1075 pThis->paSegments[i].iClassNm = idxClassData; 1076 error(pThis->pszSrc, "Unknown data (?) segment: '%s'\n", szName); 1077 } 1078 1079 /* Save the name. */ 1080 pThis->paSegments[i].pszName = strdup(szName); 1081 if (!pThis->paSegments[i].pszName) 1082 return error(pThis->pszSrc, "Out of memory!\n"); 1083 1084 /* Add the section name. */ 1085 if (!omfWriter_LNamesAdd(pThis, pThis->paSegments[i].pszName, &pThis->paSegments[i].iSegNm)) 1086 return false; 1087 1088 fHaveData |= pThis->paSegments[i].iGrpDef == idxGrpData; 1089 } 1090 } 1091 1092 if (!omfWriter_LNamesEnd(pThis)) 1093 return false; 372 1094 373 1095 /* 374 * Work the section table.1096 * Emit segment definitions. 375 1097 */ 376 bool fRet = true; 377 PIMAGE_SECTION_HEADER paShdrs = (PIMAGE_SECTION_HEADER)(pHdr + 1); 378 for (uint32_t i = 0; i < pHdr->NumberOfSections; i++) 379 { 380 if (g_cVerbose) 381 printf("shdr[%2u]: rva=%#010x cbVirt=%#010x '%-8.8s'\n" 382 " offFile=%#010x cbFile=%#010x\n" 383 " offRelocs=%#010x cRelocs=%#010x\n" 384 " offLines=%#010x cLines=%#010x Characteristics=%#010x\n", 385 i, paShdrs[i].VirtualAddress, paShdrs[i].Misc.VirtualSize, paShdrs[i].Name, 386 paShdrs[i].PointerToRawData, paShdrs[i].SizeOfRawData, 387 paShdrs[i].PointerToRelocations, paShdrs[i].NumberOfRelocations, 388 paShdrs[i].PointerToLinenumbers, paShdrs[i].NumberOfLinenumbers, paShdrs[i].Characteristics); 389 uint32_t cRelocs = paShdrs[i].NumberOfRelocations; 390 if (cRelocs > 0) 1098 uint16_t iSegDef = 1; /* Start counting at 1. */ 1099 for (uint16_t i = 0; i < cSections; i++) 1100 { 1101 if (pThis->paSegments[i].iSegDef == UINT16_MAX) 1102 continue; 1103 1104 uint8_t bSegAttr = 0; 1105 1106 /* The A field. */ 1107 switch (paShdrs[i].Characteristics & IMAGE_SCN_ALIGN_MASK) 391 1108 { 392 if ( paShdrs[i].PointerToRelocations < cbHeaders 393 || paShdrs[i].PointerToRelocations >= cbFile 394 || paShdrs[i].PointerToRelocations + cRelocs * sizeof(IMAGE_RELOCATION) > cbFile) 395 return error(pszFile, "Relocation beyond the end of the file or overlapping the headers (section #%u)\n", i); 396 397 uint32_t const cbRawData = paShdrs[i].SizeOfRawData; 398 if ( paShdrs[i].PointerToRawData < cbHeaders 399 || paShdrs[i].PointerToRawData >= cbFile 400 || paShdrs[i].PointerToRawData + cbRawData > cbFile) 401 return error(pszFile, "Raw data beyond the end of the file or overlapping the headers (section #%u)\n", i); 402 uint8_t *pbRawData = &pbFile[paShdrs[i].PointerToRawData]; 403 404 /* Is this a section which ends up in the binary? */ 405 bool const fInBinary = !(paShdrs[i].Characteristics & (IMAGE_SCN_LNK_REMOVE | IMAGE_SCN_LNK_INFO)); 406 bool const fIsPData = fInBinary 407 && memcmp(paShdrs[i].Name, RT_STR_TUPLE(".pdata\0")) == 0; 408 bool const fIsText = fInBinary 409 && (paShdrs[i].Characteristics & (IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_CNT_CODE)); 410 411 /* Whether we've seen any __ImageBase REL32 relocation that may later 412 be used with array access using the SIB encoding and ADDR32NB. */ 413 bool fSeenImageBase = false; 1109 default: 1110 case IMAGE_SCN_ALIGN_1BYTES: 1111 bSegAttr |= 1 << 5; 1112 break; 1113 case IMAGE_SCN_ALIGN_2BYTES: 1114 bSegAttr |= 2 << 5; 1115 break; 1116 case IMAGE_SCN_ALIGN_4BYTES: 1117 bSegAttr |= 5 << 5; 1118 break; 1119 case IMAGE_SCN_ALIGN_8BYTES: 1120 case IMAGE_SCN_ALIGN_16BYTES: 1121 bSegAttr |= 3 << 5; 1122 break; 1123 case IMAGE_SCN_ALIGN_32BYTES: 1124 case IMAGE_SCN_ALIGN_64BYTES: 1125 case IMAGE_SCN_ALIGN_128BYTES: 1126 case IMAGE_SCN_ALIGN_256BYTES: 1127 bSegAttr |= 4 << 5; 1128 break; 1129 case IMAGE_SCN_ALIGN_512BYTES: 1130 case IMAGE_SCN_ALIGN_1024BYTES: 1131 case IMAGE_SCN_ALIGN_2048BYTES: 1132 case IMAGE_SCN_ALIGN_4096BYTES: 1133 case IMAGE_SCN_ALIGN_8192BYTES: 1134 bSegAttr |= 6 << 5; /* page aligned, pharlabs extension. */ 1135 break; 1136 } 1137 1138 /* The C field. */ 1139 bSegAttr |= 2 << 2; /* public */ 1140 1141 /* The B field. We don't have 4GB segments, so leave it as zero. */ 1142 1143 /* The D field shall be set as we're doing USE32. */ 1144 bSegAttr |= 1; 1145 1146 1147 /* Done. */ 1148 if (!omfWriter_SegDef(pThis, bSegAttr, paShdrs[i].SizeOfRawData, 1149 pThis->paSegments[i].iSegNm, 1150 pThis->paSegments[i].iClassNm)) 1151 return false; 1152 pThis->paSegments[i].iSegDef = iSegDef++; 1153 } 1154 1155 /* 1156 * Flat group definition (#1) - special, no members. 1157 */ 1158 uint16_t iGrpDef = 1; 1159 if ( !omfWriter_GrpDefBegin(pThis, idxGrpFlat) 1160 || !omfWriter_GrpDefEnd(pThis)) 1161 return false; 1162 for (uint16_t i = 0; i < cSections; i++) 1163 if (pThis->paSegments[i].iGrpNm == idxGrpFlat) 1164 pThis->paSegments[i].iGrpDef = iGrpDef; 1165 pThis->idxGrpFlat = iGrpDef++; 1166 1167 /* 1168 * Data group definition (#2). 1169 */ 1170 /** @todo do we need to consider missing segments and ordering? */ 1171 uint16_t cGrpNms = 0; 1172 uint16_t aiGrpNms[2]; 1173 if (fHaveData) 1174 aiGrpNms[cGrpNms++] = idxGrpData; 1175 for (uint32_t iGrpNm = 0; iGrpNm < cGrpNms; iGrpNm++) 1176 { 1177 if (!omfWriter_GrpDefBegin(pThis, aiGrpNms[iGrpNm])) 1178 return false; 1179 for (uint16_t i = 0; i < cSections; i++) 1180 if (pThis->paSegments[i].iGrpNm == aiGrpNms[iGrpNm]) 1181 { 1182 pThis->paSegments[i].iGrpDef = iGrpDef; 1183 if (!omfWriter_GrpDefAddSegDef(pThis, pThis->paSegments[i].iSegDef)) 1184 return false; 1185 } 1186 if (!omfWriter_GrpDefEnd(pThis)) 1187 return false; 1188 iGrpDef++; 1189 } 1190 1191 return true; 1192 } 1193 1194 /** 1195 * This is for matching STATIC symbols with value 0 against the section name, 1196 * to see if it's a section reference or symbol at offset 0 reference. 1197 * 1198 * @returns true / false. 1199 * @param pszSymbol The symbol name. 1200 * @param pachSectName8 The section name (8-bytes). 1201 */ 1202 static bool isCoffSymbolMatchingSectionName(const char *pszSymbol, uint8_t const pachSectName8[8]) 1203 { 1204 uint32_t off = 0; 1205 char ch; 1206 while (off < 8 && (ch = pszSymbol[off]) != '\0') 1207 { 1208 if (ch != pachSectName8[off]) 1209 return false; 1210 off++; 1211 } 1212 while (off < 8) 1213 { 1214 if (!RT_C_IS_SPACE((ch = pachSectName8[off]))) 1215 return ch == '\0'; 1216 off++; 1217 } 1218 return true; 1219 } 1220 1221 static bool convertCoffSymbolsToPubDefsAndExtDefs(POMFWRITER pThis, PCIMAGE_SYMBOL paSymbols, uint16_t cSymbols, 1222 const char *pchStrTab, PCIMAGE_SECTION_HEADER paShdrs) 1223 { 1224 1225 if (!cSymbols) 1226 return true; 1227 uint32_t const cbStrTab = *(uint32_t const *)pchStrTab; 1228 char szShort[16]; 1229 1230 /* 1231 * Process the symbols the first. 1232 */ 1233 uint32_t iSymImageBase = UINT32_MAX; 1234 uint32_t cAbsSyms = 0; 1235 uint32_t cExtSyms = 0; 1236 uint32_t cPubSyms = 0; 1237 for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++) 1238 pThis->paSegments[iSeg].cPubDefs = 0; 1239 1240 for (uint16_t iSym = 0; iSym < cSymbols; iSym++) 1241 { 1242 const char *pszSymName = coffGetSymbolName(&paSymbols[iSym], pchStrTab, cbStrTab, szShort); 1243 1244 pThis->paSymbols[iSym].enmType = OMFSYMTYPE_IGNORED; 1245 pThis->paSymbols[iSym].idx = UINT16_MAX; 1246 pThis->paSymbols[iSym].idxSegDef = UINT16_MAX; 1247 pThis->paSymbols[iSym].idxGrpDef = UINT16_MAX; 1248 1249 int16_t const idxSection = paSymbols[iSym].SectionNumber; 1250 if ( (idxSection >= 1 && idxSection <= (int32_t)pThis->cSegments) 1251 || idxSection == IMAGE_SYM_ABSOLUTE) 1252 { 1253 switch (paSymbols[iSym].StorageClass) 1254 { 1255 case IMAGE_SYM_CLASS_EXTERNAL: 1256 if (idxSection != IMAGE_SYM_ABSOLUTE) 1257 { 1258 if (pThis->paSegments[idxSection - 1].iSegDef != UINT16_MAX) 1259 { 1260 pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF; 1261 pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection - 1].iSegDef; 1262 pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection - 1].iGrpDef; 1263 pThis->paSegments[idxSection - 1].cPubDefs++; 1264 cPubSyms++; 1265 } 1266 } 1267 else 1268 { 1269 pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF; 1270 pThis->paSymbols[iSym].idxSegDef = 0; 1271 pThis->paSymbols[iSym].idxGrpDef = 0; 1272 cAbsSyms++; 1273 } 1274 break; 1275 1276 case IMAGE_SYM_CLASS_STATIC: 1277 if ( paSymbols[iSym].Value == 0 1278 && idxSection != IMAGE_SYM_ABSOLUTE 1279 && isCoffSymbolMatchingSectionName(pszSymName, paShdrs[idxSection - 1].Name) ) 1280 { 1281 pThis->paSymbols[iSym].enmType = OMFSYMTYPE_SEGDEF; 1282 pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection - 1].iSegDef; 1283 pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection - 1].iGrpDef; 1284 break; 1285 } 1286 /* fall thru */ 1287 1288 case IMAGE_SYM_CLASS_END_OF_FUNCTION: 1289 case IMAGE_SYM_CLASS_AUTOMATIC: 1290 case IMAGE_SYM_CLASS_REGISTER: 1291 case IMAGE_SYM_CLASS_LABEL: 1292 case IMAGE_SYM_CLASS_MEMBER_OF_STRUCT: 1293 case IMAGE_SYM_CLASS_ARGUMENT: 1294 case IMAGE_SYM_CLASS_STRUCT_TAG: 1295 case IMAGE_SYM_CLASS_MEMBER_OF_UNION: 1296 case IMAGE_SYM_CLASS_UNION_TAG: 1297 case IMAGE_SYM_CLASS_TYPE_DEFINITION: 1298 case IMAGE_SYM_CLASS_ENUM_TAG: 1299 case IMAGE_SYM_CLASS_MEMBER_OF_ENUM: 1300 case IMAGE_SYM_CLASS_REGISTER_PARAM: 1301 case IMAGE_SYM_CLASS_BIT_FIELD: 1302 case IMAGE_SYM_CLASS_BLOCK: 1303 case IMAGE_SYM_CLASS_FUNCTION: 1304 case IMAGE_SYM_CLASS_END_OF_STRUCT: 1305 case IMAGE_SYM_CLASS_FILE: 1306 pThis->paSymbols[iSym].enmType = OMFSYMTYPE_INTERNAL; 1307 if (idxSection != IMAGE_SYM_ABSOLUTE) 1308 { 1309 pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection - 1].iSegDef; 1310 pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection - 1].iGrpDef; 1311 } 1312 else 1313 { 1314 pThis->paSymbols[iSym].idxSegDef = 0; 1315 pThis->paSymbols[iSym].idxGrpDef = 0; 1316 } 1317 break; 1318 1319 case IMAGE_SYM_CLASS_SECTION: 1320 case IMAGE_SYM_CLASS_EXTERNAL_DEF: 1321 case IMAGE_SYM_CLASS_NULL: 1322 case IMAGE_SYM_CLASS_UNDEFINED_LABEL: 1323 case IMAGE_SYM_CLASS_UNDEFINED_STATIC: 1324 case IMAGE_SYM_CLASS_CLR_TOKEN: 1325 case IMAGE_SYM_CLASS_FAR_EXTERNAL: 1326 case IMAGE_SYM_CLASS_WEAK_EXTERNAL: 1327 return error(pThis->pszSrc, "Unsupported storage class value %#x for symbol #%u (%s)\n", 1328 paSymbols[iSym].StorageClass, iSym, pszSymName); 1329 1330 default: 1331 return error(pThis->pszSrc, "Unknown storage class value %#x for symbol #%u (%s)\n", 1332 paSymbols[iSym].StorageClass, iSym, pszSymName); 1333 } 1334 } 1335 else if (idxSection == IMAGE_SYM_UNDEFINED) 1336 { 1337 if ( paSymbols[iSym].StorageClass == IMAGE_SYM_CLASS_EXTERNAL 1338 || paSymbols[iSym].StorageClass == IMAGE_SYM_CLASS_EXTERNAL_DEF) 1339 { 1340 pThis->paSymbols[iSym].enmType = OMFSYMTYPE_EXTDEF; 1341 cExtSyms++; 1342 if (iSymImageBase == UINT32_MAX && strcmp(pszSymName, "__ImageBase") == 0) 1343 iSymImageBase = iSym; 1344 } 1345 else 1346 return error(pThis->pszSrc, "Unknown/unknown storage class value %#x for undefined symbol #%u (%s)\n", 1347 paSymbols[iSym].StorageClass, iSym, pszSymName); 1348 } 1349 else if (idxSection != IMAGE_SYM_DEBUG) 1350 return error(pThis->pszSrc, "Invalid section number %#x for symbol #%u (%s)\n", idxSection, iSym, pszSymName); 1351 1352 /* Skip AUX symbols. */ 1353 uint8_t cAuxSyms = paSymbols[iSym].NumberOfAuxSymbols; 1354 while (cAuxSyms-- > 0) 1355 { 1356 iSym++; 1357 pThis->paSymbols[iSym].enmType = OMFSYMTYPE_INVALID; 1358 pThis->paSymbols[iSym].idx = UINT16_MAX; 1359 } 1360 } 1361 1362 /* 1363 * Emit the PUBDEFs the first time around (see order of records in TIS spec). 1364 */ 1365 uint16_t idxPubDef = 1; 1366 if (cPubSyms) 1367 { 1368 for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++) 1369 if (pThis->paSegments[iSeg].cPubDefs > 0) 1370 { 1371 uint16_t const idxSegDef = pThis->paSegments[iSeg].iSegDef; 1372 if (!omfWriter_PubDefBegin(pThis, pThis->paSegments[iSeg].iGrpDef, idxSegDef)) 1373 return false; 1374 for (uint16_t iSym = 0; iSym < cSymbols; iSym++) 1375 if ( pThis->paSymbols[iSym].idxSegDef == idxSegDef 1376 && pThis->paSymbols[iSym].enmType == OMFSYMTYPE_PUBDEF) 1377 { 1378 if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].Value, 1379 coffGetSymbolName(&paSymbols[iSym], pchStrTab, cbStrTab, szShort)) ) 1380 return false; 1381 pThis->paSymbols[iSym].idx = idxPubDef++; 1382 } 1383 if (!omfWriter_PubDefEnd(pThis)) 1384 return false; 1385 } 1386 } 1387 1388 if (cAbsSyms > 0) 1389 { 1390 if (!omfWriter_PubDefBegin(pThis, 0, 0)) 1391 return false; 1392 for (uint16_t iSym = 0; iSym < cSymbols; iSym++) 1393 if ( pThis->paSymbols[iSym].idxSegDef == 0 1394 && pThis->paSymbols[iSym].enmType == OMFSYMTYPE_PUBDEF) 1395 { 1396 if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].Value, 1397 coffGetSymbolName(&paSymbols[iSym], pchStrTab, cbStrTab, szShort)) ) 1398 return false; 1399 pThis->paSymbols[iSym].idx = idxPubDef++; 1400 } 1401 if (!omfWriter_PubDefEnd(pThis)) 1402 return false; 1403 } 1404 1405 /* 1406 * Go over the symbol table and emit external definition records. 1407 */ 1408 if (!omfWriter_ExtDefBegin(pThis)) 1409 return false; 1410 uint16_t idxExtDef = 1; 1411 for (uint16_t iSym = 0; iSym < cSymbols; iSym++) 1412 if (pThis->paSymbols[iSym].enmType == OMFSYMTYPE_EXTDEF) 1413 { 1414 if (!omfWriter_ExtDefAdd(pThis, coffGetSymbolName(&paSymbols[iSym], pchStrTab, cbStrTab, szShort))) 1415 return false; 1416 pThis->paSymbols[iSym].idx = idxExtDef++; 1417 } 1418 1419 /* Always add an __ImageBase reference, in case we need it to deal with ADDR32NB fixups. */ 1420 /** @todo maybe we don't actually need this and could use FLAT instead? */ 1421 if (iSymImageBase != UINT32_MAX) 1422 pThis->idxExtImageBase = pThis->paSymbols[iSymImageBase].idx; 1423 else if (omfWriter_ExtDefAdd(pThis, "__ImageBase")) 1424 pThis->idxExtImageBase = idxExtDef; 1425 else 1426 return false; 1427 1428 if (!omfWriter_ExtDefEnd(pThis)) 1429 return false; 1430 1431 return true; 1432 } 1433 1434 1435 static bool convertCoffSectionsToLeDataAndFixupps(POMFWRITER pThis, uint8_t const *pbFile, size_t cbFile, 1436 PCIMAGE_SECTION_HEADER paShdrs, uint16_t cSections, 1437 PCIMAGE_SYMBOL paSymbols, uint16_t cSymbols, const char *pchStrTab) 1438 { 1439 uint32_t const cbStrTab = *(uint32_t const *)pchStrTab; 1440 bool fRet = true; 1441 for (uint32_t i = 0; i < pThis->cSegments; i++) 1442 { 1443 if (pThis->paSegments[i].iSegDef == UINT16_MAX) 1444 continue; 1445 1446 char szShortName[16]; 1447 const char *pszSegNm = pThis->paSegments[i].pszName; 1448 uint16_t cRelocs = paShdrs[i].NumberOfRelocations; 1449 PCIMAGE_RELOCATION paRelocs = (PCIMAGE_RELOCATION)&pbFile[paShdrs[i].PointerToRelocations]; 1450 uint32_t cbVirtData = paShdrs[i].SizeOfRawData; 1451 uint32_t cbData = paShdrs[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA ? 0 : cbVirtData; 1452 uint8_t const *pbData = &pbFile[paShdrs[i].PointerToRawData]; 1453 uint32_t off = 0; 1454 1455 /* Check that the relocations are sorted and within the section. */ 1456 for (uint32_t iReloc = 1; iReloc < cRelocs; iReloc++) 1457 if (paRelocs[iReloc - 1].u.VirtualAddress >= paRelocs[iReloc].u.VirtualAddress) 1458 return error(pThis->pszSrc, "Section #%u (%s) relocations aren't sorted\n", i, pszSegNm); 1459 if ( cRelocs > 0 1460 && paRelocs[cRelocs - 1].u.VirtualAddress - paShdrs[i].VirtualAddress 1461 + COFF_AMD64_RELOC_SIZE(paRelocs[cRelocs - 1].Type) > cbVirtData) 1462 return error(pThis->pszSrc, 1463 "Section #%u (%s) relocations beyond section data! cbVirtData=%#x RvaFix=%#x RVASeg=%#x type=%#x\n", 1464 i, pszSegNm, cbVirtData, paRelocs[cRelocs - 1].u.VirtualAddress, paShdrs[i].VirtualAddress, 1465 paRelocs[cRelocs - 1].Type); 1466 1467 /* The OMF record size requires us to split larger sections up. To make 1468 life simple, we fill zeros for unitialized (BSS) stuff. */ 1469 const uint32_t cbMaxData = RT_MIN(OMF_MAX_RECORD_PAYLOAD - 1 - (pThis->paSegments[i].iSegDef >= 128) - 4 - 1, _1K); 1470 while (cbVirtData > 0) 1471 { 1472 /* Figure out how many bytes to put out in this chunk. Must make sure 1473 fixups doesn't cross chunk boundraries. ASSUMES sorted relocs. */ 1474 uint32_t cChunkRelocs = cRelocs; 1475 uint32_t cbChunk = cbVirtData; 1476 uint32_t uRvaEnd = paShdrs[i].VirtualAddress + off + cbChunk; 1477 if (cbChunk > cbMaxData) 1478 { 1479 cbChunk = cbMaxData; 1480 uRvaEnd = paShdrs[i].VirtualAddress + off + cbChunk; 1481 cChunkRelocs = 0; 1482 1483 /* Quickly determin the reloc range. */ 1484 while ( cChunkRelocs < cRelocs 1485 && paRelocs[cChunkRelocs].u.VirtualAddress < uRvaEnd) 1486 cChunkRelocs++; 1487 1488 /* Ensure final reloc doesn't go beyond chunk. */ 1489 while ( cChunkRelocs > 0 1490 && paRelocs[cChunkRelocs - 1].u.VirtualAddress + COFF_AMD64_RELOC_SIZE(paRelocs[cChunkRelocs - 1].Type) 1491 > uRvaEnd) 1492 { 1493 uint32_t cbDrop = uRvaEnd - paRelocs[cChunkRelocs - 1].u.VirtualAddress; 1494 cbChunk -= cbDrop; 1495 uRvaEnd -= cbDrop; 1496 cChunkRelocs--; 1497 } 1498 1499 if (!cbVirtData) 1500 return error(pThis->pszSrc, "Wtf? cbVirtData is zero!\n"); 1501 } 414 1502 415 1503 /* 416 * Convert from AMD64 fixups to I386 ones, assuming 64-bit addresses 417 * being fixed up doesn't need the high dword and that it's 418 * appropriately initialized already. 1504 * We stash the bytes into the OMF writer record buffer, receiving a 1505 * pointer to the start of it so we can make adjustments if necessary. 419 1506 */ 420 PIMAGE_RELOCATION paRelocs = (PIMAGE_RELOCATION)&pbFile[paShdrs[i].PointerToRelocations]; 421 for (uint32_t j = 0; j < cRelocs; j++) 422 { 1507 uint8_t *pbCopy; 1508 if (!omfWriter_LEDataBegin(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy)) 1509 return false; 1510 1511 /* 1512 * Convert fiuxps. 1513 */ 1514 uint32_t const uRvaChunk = paShdrs[i].VirtualAddress + off; 1515 for (uint32_t iReloc = 0; iReloc < cChunkRelocs; iReloc++) 1516 { 1517 /* Get the OMF and COFF data for the symbol the reloc references. */ 1518 if (paRelocs[iReloc].SymbolTableIndex >= pThis->cSymbols) 1519 return error(pThis->pszSrc, "Relocation symtab index (%#x) is out of range in segment #%u '%s'\n", 1520 paRelocs[iReloc].SymbolTableIndex, i, pszSegNm); 1521 PCIMAGE_SYMBOL pCoffSym = &paSymbols[paRelocs[iReloc].SymbolTableIndex]; 1522 POMFSYMBOL pOmfSym = &pThis->paSymbols[paRelocs[iReloc].SymbolTableIndex]; 1523 1524 /* Calc fixup location in the pending chunk and setup a flexible pointer to it. */ 1525 uint16_t offDataRec = (uint16_t)paRelocs[iReloc].u.VirtualAddress - uRvaChunk; 423 1526 RTPTRUNION uLoc; 424 uLoc.pu8 = paRelocs[j].u.VirtualAddress < cbRawData ? &pbRawData[paRelocs[j].u.VirtualAddress] : NULL; 425 426 /* Print it. */ 427 if (g_cVerbose > 1) 1527 uLoc.pu8 = &pbCopy[offDataRec]; 1528 1529 /* OMF fixup data initialized with typical defaults. */ 1530 bool fSelfRel = true; 1531 uint8_t bLocation = OMF_FIX_LOC_32BIT_OFFSET; 1532 uint8_t bFrame = OMF_FIX_F_GRPDEF; 1533 uint16_t idxFrame = pThis->idxGrpFlat; 1534 uint8_t bTarget; 1535 uint16_t idxTarget; 1536 bool fTargetDisp; 1537 uint32_t offTargetDisp; 1538 switch (pOmfSym->enmType) 428 1539 { 429 size_t off = printf("%#010x %#010x", paRelocs[j].u.VirtualAddress, paRelocs[j].SymbolTableIndex); 430 switch (paRelocs[j].Type) 431 { 432 case IMAGE_REL_AMD64_ADDR64: 433 if (uLoc.pu64) 434 off += printf(" %#018" ELF_FMT_X64 "", *uLoc.pu64); 435 break; 436 case IMAGE_REL_AMD64_ADDR32: 437 case IMAGE_REL_AMD64_ADDR32NB: 438 case IMAGE_REL_AMD64_REL32: 439 case IMAGE_REL_AMD64_REL32_1: 440 case IMAGE_REL_AMD64_REL32_2: 441 case IMAGE_REL_AMD64_REL32_3: 442 case IMAGE_REL_AMD64_REL32_4: 443 case IMAGE_REL_AMD64_REL32_5: 444 case IMAGE_REL_AMD64_SECREL: 445 if (uLoc.pu32) 446 off += printf(" %#010x", *uLoc.pu32); 447 break; 448 case IMAGE_REL_AMD64_SECTION: 449 if (uLoc.pu16) 450 off += printf(" %#06x", *uLoc.pu16); 451 break; 452 case IMAGE_REL_AMD64_SECREL7: 453 if (uLoc.pu8) 454 off += printf(" %#04x", *uLoc.pu8); 455 break; 456 } 457 while (off < 36) 458 off += printf(" "); 459 printf(" %s %s\n", 460 paRelocs[j].Type < RT_ELEMENTS(g_apszCoffAmd64RelTypes) 461 ? g_apszCoffAmd64RelTypes[paRelocs[j].Type] : "unknown", 462 coffGetSymbolName(&paSymTab[paRelocs[j].SymbolTableIndex], pchStrTab, szShortName)); 1540 case OMFSYMTYPE_INTERNAL: 1541 case OMFSYMTYPE_PUBDEF: 1542 bTarget = OMF_FIX_T_SEGDEF; 1543 idxTarget = pOmfSym->idxSegDef; 1544 fTargetDisp = true; 1545 offTargetDisp = pCoffSym->Value; 1546 break; 1547 1548 case OMFSYMTYPE_SEGDEF: 1549 bTarget = OMF_FIX_T_SEGDEF_NO_DISP; 1550 idxTarget = pOmfSym->idxSegDef; 1551 fTargetDisp = false; 1552 offTargetDisp = 0; 1553 break; 1554 1555 case OMFSYMTYPE_EXTDEF: 1556 bTarget = OMF_FIX_T_EXTDEF_NO_DISP; 1557 idxTarget = pOmfSym->idx; 1558 fTargetDisp = false; 1559 offTargetDisp = 0; 1560 break; 1561 1562 default: 1563 return error(pThis->pszSrc, "Relocation in segment #%u '%s' references ignored or invalid symbol (%s)\n", 1564 i, pszSegNm, coffGetSymbolName(pCoffSym, pchStrTab, cbStrTab, szShortName)); 463 1565 } 464 1566 465 /* Convert it. */ 466 uint8_t uDir = IMAGE_REL_AMD64_ABSOLUTE; 467 switch (paRelocs[j].Type) 1567 /* Do COFF relocation type conversion. */ 1568 switch (paRelocs[iReloc].Type) 468 1569 { 469 1570 case IMAGE_REL_AMD64_ADDR64: 470 1571 { 471 uint64_t uAddend = 0; 472 if (uLoc.pu64) 473 { 474 if (paRelocs[j].u.VirtualAddress + 8 > cbRawData) 475 return error(pszFile, "ADDR64 at %#x in section %u '%-8.8s' not fully in raw data\n", 476 paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name); 477 uAddend = *uLoc.pu64; 478 } 1572 uint64_t uAddend = *uLoc.pu64; 479 1573 if (uAddend > _1G) 480 return error(pszFile, "ADDR64 with large addend (%#llx) at %#x in section %u '%-8.8s'\n", 481 uAddend, paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name); 482 paRelocs[j].Type = IMAGE_REL_I386_DIR32; 483 uDir = IMAGE_REL_AMD64_ADDR64; 1574 fRet = error(pThis->pszSrc, "ADDR64 with large addend (%#llx) at %#x in segment #%u '%s'\n", 1575 uAddend, paRelocs[iReloc].u.VirtualAddress, i, pszSegNm); 1576 fSelfRel = false; 484 1577 break; 485 1578 } … … 490 1583 case IMAGE_REL_AMD64_REL32_4: 491 1584 case IMAGE_REL_AMD64_REL32_5: 492 { 493 if (paRelocs[j].u.VirtualAddress + 4 > cbRawData) 494 return error(pszFile, "%s at %#x in section %u '%-8.8s' is not (fully) in raw data\n", 495 g_apszCoffAmd64RelTypes[paRelocs[j].Type], paRelocs[j].u.VirtualAddress, i, 496 paShdrs[i].Name); 497 *uLoc.pu32 += paRelocs[j].Type - IMAGE_REL_AMD64_REL32; 498 paRelocs[j].Type = IMAGE_REL_I386_REL32; 1585 /** @todo Check whether OMF read addends from the data or relies on the 1586 * displacement. Also, check what it's relative to. */ 1587 *uLoc.pu32 += paRelocs[iReloc].Type - IMAGE_REL_AMD64_REL32; 499 1588 break; 500 } 501 502 /* These are 1:1 conversions: */ 1589 503 1590 case IMAGE_REL_AMD64_ADDR32: 504 #if 1 /* Turns out this is special when wlink is doing DOS/BIOS binaries. */ 505 /** @todo this still doesn't work for bs3-cmn-SelProtFar32ToFlat32.obj!! */ 506 paRelocs[j].Type = IMAGE_REL_I386_ABSOLUTE; /* Note! Don't believe MS pecoff.doc, this works with wlink. */ 507 #else 508 paRelocs[j].Type = IMAGE_REL_I386_DIR32; 509 uDir = IMAGE_REL_AMD64_ADDR32; 510 #endif 1591 fSelfRel = false; 511 1592 break; 1593 512 1594 case IMAGE_REL_AMD64_ADDR32NB: 513 if (fSeenImageBase && fIsText) /* This is voodoo. */ 514 paRelocs[j].Type = IMAGE_REL_I386_ABSOLUTE; /* Note! Don't believe MS pecoff.doc, this works with wlink. */ 1595 fSelfRel = false; 1596 bFrame = OMF_FIX_F_EXTDEF; 1597 idxFrame = pThis->idxExtImageBase; 1598 break; 1599 1600 case IMAGE_REL_AMD64_REL32: 1601 /* defaults are ok. */ 1602 break; 1603 1604 case IMAGE_REL_AMD64_SECTION: 1605 bLocation = OMF_FIX_LOC_16BIT_SEGMENT; 1606 /* fall thru */ 1607 1608 case IMAGE_REL_AMD64_SECREL: 1609 fSelfRel = false; 1610 if (pOmfSym->enmType == OMFSYMTYPE_EXTDEF) 1611 { 1612 bFrame = OMF_FIX_F_EXTDEF; 1613 idxFrame = pOmfSym->idx; 1614 } 515 1615 else 516 1616 { 517 paRelocs[j].Type = IMAGE_REL_I386_DIR32NB;518 uDir = IMAGE_REL_AMD64_ADDR32NB;1617 bFrame = OMF_FIX_F_SEGDEF; 1618 idxFrame = pOmfSym->idxSegDef; 519 1619 } 520 1620 break; 521 case IMAGE_REL_AMD64_REL32: 522 paRelocs[j].Type = IMAGE_REL_I386_REL32; 523 524 /* This is voodoo! */ 525 if ( fIsText 526 && strcmp(coffGetSymbolName(&paSymTab[paRelocs[j].SymbolTableIndex], pchStrTab, szShortName), 527 "__ImageBase") == 0) 528 { 529 if ( (uLoc.pu8[-1] & (X86_MODRM_MOD_MASK | X86_MODRM_RM_MASK)) == 5 /* disp32 + wrt */ 530 && uLoc.pu8[-2] == 0x8d /* LEA */ 531 && (uLoc.pu8[-3] & (0xf8 | X86_OP_REX_W)) == X86_OP_REX_W /* 64-bit reg */ ) 532 { 533 if (*uLoc.pu32) 534 { 535 error(pszFile, "__ImageBase fixup with disp %#x at rva=%#x in section #%u '%-8.8s'!\n", 536 *uLoc.pu32, paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name); 537 fRet = false; 538 } 539 540 if (fSeenImageBase) 541 return error(pszFile, "More than one __ImageBase fixup! 2nd at rva=%#x in section #%u '%-8.8s'\n", 542 paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name); 543 if (g_cVerbose) 544 printf("Applying __ImageBase hack at rva=%#x in section #%u '%-8.8s'\n", 545 paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name); 546 547 /* Convert it into a mov reg, dword 0. Leave the extra rex prefix, as it will be ignored. */ 548 uint8_t iReg = (uLoc.pu8[-1] >> X86_MODRM_REG_SHIFT) & X86_MODRM_REG_SMASK; 549 uLoc.pu8[-1] = 0xb8 | iReg; 550 uLoc.pu8[-2] = X86_OP_REX_R & uLoc.pu8[-3]; 551 fSeenImageBase = true; 552 553 /* Neutralize the fixup. 554 Note! wlink takes the IMAGE_REL_I386_ABSOLUTE fixups seriously, so we cannot use that 555 to disable it, so instead we have to actually remove it from the fixup table. */ 556 cRelocs--; 557 if (j != cRelocs) 558 memmove(&paRelocs[j], &paRelocs[j + 1], (cRelocs - j) * sizeof(paRelocs[j])); 559 paShdrs[i].NumberOfRelocations = (uint16_t)cRelocs; 560 j--; 561 } 562 else 563 { 564 error(pszFile, "__ImageBase fixup that isn't a recognized LEA at rva=%#x in section #%u '%-8.8s'!\n", 565 paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name); 566 fRet = false; 567 } 568 } 569 break; 570 case IMAGE_REL_AMD64_SECTION: 571 paRelocs[j].Type = IMAGE_REL_I386_SECTION; 572 break; 573 case IMAGE_REL_AMD64_SECREL: 574 paRelocs[j].Type = IMAGE_REL_I386_SECREL; 575 break; 1621 1622 case IMAGE_REL_AMD64_ABSOLUTE: 1623 continue; /* Ignore it like the PECOFF.DOC says we should. */ 1624 576 1625 case IMAGE_REL_AMD64_SECREL7: 577 paRelocs[j].Type = IMAGE_REL_I386_SECREL7;578 break;579 case IMAGE_REL_AMD64_ABSOLUTE:580 paRelocs[j].Type = IMAGE_REL_I386_ABSOLUTE;581 /* Turns out wlink takes this seriously, so it usage must be checked out. */582 error(pszFile, "ABSOLUTE fixup at rva=%#x in section #%u '%-8.8s'\n",583 paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name);584 fRet = false;585 break;586 587 1626 default: 588 return error(p szFile, "Unsupported fixup type %#x (%s) at rva=%#x in section #%u '%-8.8s'\n",589 paRelocs[ j].Type,590 paRelocs[ j].Type < RT_ELEMENTS(g_apszCoffAmd64RelTypes)591 ? g_apszCoffAmd64RelTypes[paRelocs[ j].Type] : "unknown",592 paRelocs[ j].u.VirtualAddress, i, paShdrs[i].Name);1627 return error(pThis->pszSrc, "Unsupported fixup type %#x (%s) at rva=%#x in section #%u '%-8.8s'\n", 1628 paRelocs[iReloc].Type, 1629 paRelocs[iReloc].Type < RT_ELEMENTS(g_apszCoffAmd64RelTypes) 1630 ? g_apszCoffAmd64RelTypes[paRelocs[iReloc].Type] : "unknown", 1631 paRelocs[iReloc].u.VirtualAddress, i, paShdrs[i].Name); 593 1632 } 594 1633 595 /* 596 * Error no absolute fixup that we care about. We continue so 597 * the developer can get the full story before failing. 598 */ 599 if ( fInBinary 600 && !fIsPData 601 && uDir != IMAGE_REL_AMD64_ABSOLUTE) 602 { 603 error(pszFile, "%s at %#x in section %u '%-8.8s': wlink won't get this right\n", 604 g_apszCoffAmd64RelTypes[uDir], paRelocs[j].u.VirtualAddress, i, paShdrs[i].Name); 605 fRet = false; 606 } 607 } 1634 /* Add the fixup. */ 1635 if (idxFrame == UINT16_MAX) 1636 error(pThis->pszSrc, "idxFrame=UINT16_MAX for %s type=%s\n", 1637 coffGetSymbolName(pCoffSym, pchStrTab, cbStrTab, szShortName), 1638 g_apszCoffAmd64RelTypes[paRelocs[iReloc].Type]); 1639 fRet = omfWriter_LEDataAddFixup(pThis, offDataRec, fSelfRel, bLocation, bFrame, idxFrame, 1640 bTarget, idxTarget, fTargetDisp, offTargetDisp) && fRet; 1641 } 1642 1643 /* 1644 * Write the LEDATA and associated FIXUPPs. 1645 */ 1646 if (!omfWriter_LEDataEnd(pThis)) 1647 return false; 1648 1649 /* 1650 * Advance. 1651 */ 1652 paRelocs += cChunkRelocs; 1653 cRelocs -= cChunkRelocs; 1654 if (cbData > cbChunk) 1655 { 1656 cbData -= cbChunk; 1657 pbData += cbChunk; 1658 } 1659 else 1660 cbData = 0; 1661 off += cbChunk; 1662 cbVirtData -= cbChunk; 608 1663 } 609 1664 } 1665 610 1666 return fRet; 611 1667 } 612 1668 613 1669 614 /** @name Selected OMF record types. 615 * @{ */ 616 #define PUBDEF UINT8_C(0x90) 617 #define LPUBDEF UINT8_C(0xb6) 618 #define THEADR UINT8_C(0x80) 619 #define EXTDEF UINT8_C(0x8c) 620 #define SEGDEF UINT8_C(0x98) 621 #define LNAMES UINT8_C(0x96) 622 #define GRPDEF UINT8_C(0x9a) 623 #define REC32 UINT8_C(0x01) /**< Flag indicating 32-bit record. */ 624 /** @} */ 1670 static bool convertCoffToOmf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, FILE *pDst) 1671 { 1672 /* 1673 * Validate the source file a little. 1674 */ 1675 if (!validateCoff(pszFile, pbFile, cbFile)) 1676 return false; 1677 1678 /* 1679 * Instantiate the OMF writer. 1680 */ 1681 PIMAGE_FILE_HEADER pHdr = (PIMAGE_FILE_HEADER)pbFile; 1682 POMFWRITER pThis = omfWriter_Create(pszFile, pHdr->NumberOfSections, pHdr->NumberOfSymbols, pDst); 1683 if (!pThis) 1684 return false; 1685 1686 /* 1687 * Write the OMF object file. 1688 */ 1689 if (omfWriter_BeginModule(pThis, pszFile)) 1690 { 1691 PCIMAGE_SECTION_HEADER paShdrs = (PCIMAGE_SECTION_HEADER)(pHdr + 1); 1692 PCIMAGE_SYMBOL paSymTab = (PCIMAGE_SYMBOL)&pbFile[pHdr->PointerToSymbolTable]; 1693 const char *pchStrTab = (const char *)&paSymTab[pHdr->NumberOfSymbols]; 1694 if ( convertCoffSectionsToSegDefsAndGrpDefs(pThis, paShdrs, pHdr->NumberOfSections) 1695 && convertCoffSymbolsToPubDefsAndExtDefs(pThis, paSymTab, pHdr->NumberOfSymbols, pchStrTab, paShdrs) 1696 && omfWriter_LinkPassSeparator(pThis) 1697 && convertCoffSectionsToLeDataAndFixupps(pThis, pbFile, cbFile, paShdrs, pHdr->NumberOfSections, 1698 paSymTab, pHdr->NumberOfSymbols, pchStrTab) 1699 1700 && omfWriter_EndModule(pThis) ) 1701 { 1702 1703 omfWriter_Destroy(pThis); 1704 return true; 1705 } 1706 } 1707 1708 omfWriter_Destroy(pThis); 1709 return false; 1710 1711 } 1712 1713 1714 1715 /********************************************************************************************************************************* 1716 * OMF Converter/Tweaker * 1717 *********************************************************************************************************************************/ 625 1718 626 1719 /** Watcom intrinsics we need to modify so we can mix 32-bit and 16-bit … … 684 1777 return error(pszFile, "Invalid record length at %#x: %#x (cbFile=%#lx)\n", off, cbRec, (unsigned long)cbFile); 685 1778 686 if (bRecType & REC32)1779 if (bRecType & OMF_REC32) 687 1780 fProbably32bit = true; 688 1781 … … 698 1791 * Scan external definitions for intrinsics needing mangling. 699 1792 */ 700 case EXTDEF:1793 case OMF_EXTDEF: 701 1794 { 702 1795 while (offRec + 1 < cbRec) … … 749 1842 * Record LNAME records, scanning for FLAT. 750 1843 */ 751 case LNAMES:1844 case OMF_LNAMES: 752 1845 { 753 1846 while (offRec + 1 < cbRec) … … 775 1868 * Display public names if -v is specified. 776 1869 */ 777 case PUBDEF:778 case PUBDEF | REC32:779 case LPUBDEF:780 case LPUBDEF | REC32:1870 case OMF_PUBDEF16: 1871 case OMF_PUBDEF32: 1872 case OMF_LPUBDEF16: 1873 case OMF_LPUBDEF32: 781 1874 { 782 1875 if (g_cVerbose > 0) 783 1876 { 784 char const chType = bRecType == PUBDEF || bRecType == (PUBDEF | REC32)? 'T' : 't';1877 char const chType = bRecType == OMF_PUBDEF16 || bRecType == OMF_PUBDEF32 ? 'T' : 't'; 785 1878 const char *pszRec = "LPUBDEF"; 786 1879 if (chType == 'T') … … 816 1909 817 1910 uint32_t offSeg; 818 if (bRecType & REC32)1911 if (bRecType & OMF_REC32) 819 1912 { 820 1913 OMF_CHECK_RET(4, [L]PUBDEF); … … 861 1954 static int convertit(const char *pszFile) 862 1955 { 1956 /* Construct the filename for saving the unmodified file. */ 1957 char szOrgFile[_4K]; 1958 size_t cchFile = strlen(pszFile); 1959 if (cchFile + sizeof(".original") > sizeof(szOrgFile)) 1960 { 1961 error(pszFile, "Filename too long!\n"); 1962 return RTEXITCODE_FAILURE; 1963 } 1964 memcpy(szOrgFile, pszFile, cchFile); 1965 memcpy(&szOrgFile[cchFile], ".original", sizeof(".original")); 1966 1967 /* Read the whole file. */ 863 1968 void *pvFile; 864 1969 size_t cbFile; 865 1970 if (readfile(pszFile, &pvFile, &cbFile)) 866 1971 { 1972 /* 1973 * Do format conversions / adjustments. 1974 */ 867 1975 bool fRc = false; 868 1976 uint8_t *pbFile = (uint8_t *)pvFile; … … 872 1980 && pbFile[2] == ELFMAG2 873 1981 && pbFile[3] == ELFMAG3) 874 fRc = convertelf(pszFile, pbFile, cbFile); 1982 /** @todo convertElfToOmf(). */ 1983 fRc = writefile(szOrgFile, pvFile, cbFile) 1984 && convertelf(pszFile, pbFile, cbFile) 1985 && writefile(pszFile, pvFile, cbFile); 875 1986 else if ( cbFile > sizeof(IMAGE_FILE_HEADER) 876 1987 && RT_MAKE_U16(pbFile[0], pbFile[1]) == IMAGE_FILE_MACHINE_AMD64 … … 878 1989 < cbFile 879 1990 && RT_MAKE_U16(pbFile[2], pbFile[3]) > 0) 880 fRc = convertcoff(pszFile, pbFile, cbFile); 1991 { 1992 if (writefile(szOrgFile, pvFile, cbFile)) 1993 { 1994 FILE *pDst = openfile(pszFile, true /*fWrite*/); 1995 if (pDst) 1996 { 1997 fRc = convertCoffToOmf(pszFile, pbFile, cbFile, pDst); 1998 fRc = fclose(pDst) == 0 && fRc; 1999 } 2000 } 2001 } 881 2002 else if ( cbFile >= 8 882 && pbFile[0] == THEADR2003 && pbFile[0] == OMF_THEADR 883 2004 && RT_MAKE_U16(pbFile[1], pbFile[2]) < cbFile) 884 2005 { 885 2006 const char **papchLNames = (const char **)calloc(sizeof(*papchLNames), _32K); 886 fRc = convertomf(pszFile, pbFile, cbFile, papchLNames, _32K); 2007 fRc = writefile(szOrgFile, pvFile, cbFile) 2008 && convertomf(pszFile, pbFile, cbFile, papchLNames, _32K) 2009 && writefile(pszFile, pvFile, cbFile); 887 2010 free(papchLNames); 888 2011 } … … 890 2013 fprintf(stderr, "error: Don't recognize format of '%s' (%#x %#x %#x %#x, cbFile=%lu)\n", 891 2014 pszFile, pbFile[0], pbFile[1], pbFile[2], pbFile[3], (unsigned long)cbFile); 892 if (fRc)893 fRc = writefile(pszFile, pvFile, cbFile);894 2015 free(pvFile); 895 2016 if (fRc) -
trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-MemAlloc.c
r58814 r59932 43 43 */ 44 44 PBS3SLABHEAD pHead = enmKind == BS3MEMKIND_REAL 45 ? &BS3_ MSC64_FIXUP_HACK(BS3SLABHEAD, BS3_DATA_NM(g_aBs3LowSlabLists))[idxSlabList]46 : &BS3_ MSC64_FIXUP_HACK(BS3SLABHEAD, BS3_DATA_NM(g_aBs3UpperTiledSlabLists))[idxSlabList];45 ? &BS3_DATA_NM(g_aBs3LowSlabLists)[idxSlabList] 46 : &BS3_DATA_NM(g_aBs3UpperTiledSlabLists)[idxSlabList]; 47 47 48 BS3_ASSERT(BS3_ MSC64_FIXUP_HACK(BS3SLABHEAD, BS3_DATA_NM(g_aBs3LowSlabLists))[idxSlabList].cbChunk >= cb);48 BS3_ASSERT(BS3_DATA_NM(g_aBs3LowSlabLists)[idxSlabList].cbChunk >= cb); 49 49 pvRet = Bs3SlabListAlloc(pHead); 50 50 if (pvRet) -
trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-cmn-memory.h
r58814 r59932 72 72 { 73 73 unsigned idx = cbRequest ? ASMBitLastSetU16((uint16_t)(cbRequest - 1)) : 0; 74 return BS3_ MSC64_FIXUP_HACK(uint8_t const, BS3_DATA_NM(g_aiBs3SlabListsByPowerOfTwo))[idx];74 return BS3_DATA_NM(g_aiBs3SlabListsByPowerOfTwo)[idx]; 75 75 } 76 76 return UINT8_MAX; -
trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-common.mac
r59900 r59932 123 123 124 124 %ifdef ASM_FORMAT_OMF 125 section TEXT64 align=4 CLASS=CODE PUBLIC USE32125 ;section TEXT64 align=4 CLASS=CODE PUBLIC USE32 126 126 ;section .text align=4 CLASS=CODE PUBLIC USE32 - nasm doesn't do '.' at the start of segments in OMF mode. Not that this helps anyways... 127 127 ;section .rdata align=4 CLASS=CODE PUBLIC USE32 … … 132 132 section BS3TEXT64_END align=1 progbits alloc exec nowrite 133 133 %else 134 section BS3TEXT64_END align=1 CLASS= CODEPUBLIC USE32 FLAT134 section BS3TEXT64_END align=1 CLASS=BS3CODE64 PUBLIC USE32 FLAT 135 135 %endif 136 136 BS3_GLOBAL_DATA Bs3Text64_EndOfSegment, 0 … … 171 171 ;section .pdata align=8 CLASS=DATA PUBLIC USE32 172 172 ;section .bss align=8 CLASS=DATA PUBLIC USE32 173 section BS3DATA64_END align=16 CLASS= DATA PUBLIC USE32173 section BS3DATA64_END align=16 CLASS=FAR_DATA PUBLIC USE32 174 174 %endif 175 175 BS3_GLOBAL_DATA Bs3Data64_EndOfSegment, 0 … … 177 177 %ifndef ASM_FORMAT_ELF 178 178 ;GROUP BS3DATA64_GROUP BS3DATA64 .data .rdata .xdata .pdata .bss BS3DATA64_END 179 GROUP DGROUP BS3DATA64 BS3DATA64_END179 GROUP BS3DATA64_GROUP BS3DATA64 BS3DATA64_END 180 180 %endif 181 181 -
trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3-first-pe16.asm
r59287 r59932 44 44 BS3_EXTERN_SYSTEM16 Bs3Lidt_Idt16 45 45 46 extern Bs3SelProtFar32ToFlat32_c64 47 extern Bs3PrintChr_c64 48 extern Bs3Printf_c64 49 extern Bs3TestTerm_c64 50 extern Bs3TestSub_c64 51 extern Bs3TestInit_c64 52 46 53 BS3_BEGIN_TEXT16 54 EXTERN Bs3InitMemory_rm 55 56 %if 0 47 57 EXTERN Main_pe16 48 58 EXTERN Bs3SwitchToPE16_rm … … 64 74 EXTERN Bs3SwitchToRM_pae32 65 75 extern Bs3SwitchToRM_lm64 66 EXTERN Bs3InitMemory_rm 76 extern _Bs3PrintChr_c16 77 extern _Bs3PrintChr_c32 78 extern Bs3PrintChr_c64 79 %endif 80 67 81 BS3_EXTERN_CMN Bs3Shutdown 68 82 BS3_EXTERN_CMN Bs3Trap32Init 69 83 70 extern _Bs3PrintChr_c1671 extern _Bs3PrintChr_c3272 extern Bs3PrintChr_c6473 84 74 85 BS3_BEGIN_TEXT16 … … 79 90 call Bs3Trap32Init 80 91 sub xSP, 20h ; for 64-bit calls. 92 %if 0 81 93 call NAME(Bs3SwitchToPE16_rm) 82 94 push '1' … … 154 166 push 'g' 155 167 call NAME(Bs3PrintChr_c16) 168 %endif 156 169 157 170 ; … … 161 174 hlt 162 175 jmp .halt 163 call NAME(Main_pe16)176 ; call NAME(Main_pe16) 164 177 call Bs3Shutdown 165 178 -
trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.h
r59895 r59932 455 455 # define BS3_DATA_NM(a_Name) a_Name 456 456 #endif 457 458 /** @def BS3_MSC64_FIXUP_HACK459 * Used to avoid IMAGE_REL_AMD64_ADDR32NB fixups where the compiler tries to460 * make use of __ImageBase as a base pointer instead of emitting rip relative461 * accesses. Happens when there are a bunch of global data accesses in the same462 * function, probably to save space.463 *464 * The volatile variable in the lambda fixes it.465 */466 #if _MSC_VER && ARCH_BITS == 64467 # define BS3_MSC64_FIXUP_HACK(a_BaseType, a_Data) \468 ([]() -> a_BaseType * \469 { \470 a_BaseType * volatile x = a_Data; \471 return x; \472 }())473 474 #else475 # define BS3_MSC64_FIXUP_HACK(a_BaseType, a_Data) (a_Data)476 #endif477 478 457 479 458 /** -
trunk/src/VBox/ValidationKit/bootsectors/bs3kit/bs3kit.mac
r59878 r59932 379 379 section BS3TEXT64 align=1 progbits alloc exec nowrite 380 380 %else 381 section BS3TEXT64 align=1 CLASS= CODE PUBLIC USE32 FLAT ; class=CODE here because of 64-bit cl and/or wlink.exe381 section BS3TEXT64 align=1 CLASS=BS3CODE64 PUBLIC USE32 FLAT 382 382 %endif 383 383 %else … … 393 393 section BS3DATA64 align=16 progbits alloc noexec write 394 394 %else 395 section BS3DATA64 align=16 CLASS= DATA PUBLIC USE32 ;FLAT (see DATA32) ; class=DATA here because of 64-bit cl and/or wlink.exe395 section BS3DATA64 align=16 CLASS=FAR_DATA PUBLIC USE32 ;FLAT (see DATA32) 396 396 %endif 397 397 %else
Note:
See TracChangeset
for help on using the changeset viewer.