COFF: Allow hex literals in .def files: BASE/HEAPSIZE/STACKSIZE (#184764)

For a Win32 DLL, a .def file can have a custom executable base:
```
LIBRARY "stub.dll" BASE=0x10000000
```

Currently the parser enforces Base 10, but [Microsoft's
documentation](https://learn.microsoft.com/en-us/cpp/build/reference/rules-for-module-definition-statements?view=msvc-170)
states "Numeric arguments are specified in base 10 or hexadecimal".

This fixes that, and also HEAPSIZE and STACKSIZE (which use the same
function).

There are a few more instances of `getAsInteger` that expect base10 -
for ordinals and the VERSION directive. Since I don't have an
in-the-wild example of a .def file using hexadecimal for these, I am
wary about changing those too.
This commit is contained in:
Will
2026-03-06 02:01:58 +10:00
committed by GitHub
parent 38a8bccdce
commit e9657a12b2
4 changed files with 28 additions and 1 deletions

View File

@@ -12,6 +12,15 @@
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=BASE-HEADER %s
# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=BASE-TEXT %s
# RUN: echo "LIBRARY \"%t.dll\" BASE=0x280000000" > %t.def
# RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.dll | FileCheck -check-prefix=BASE-HEADER %s
# RUN: llvm-objdump -s %t.dll | FileCheck --check-prefix=BASE-TEXT %s
# RUN: echo "LIBRARY \"%t.dll\" BASE=10737418240" > %t.def
# RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.dll | FileCheck -check-prefix=BASE-HEADER %s
# RUN: llvm-objdump -s %t.dll | FileCheck --check-prefix=BASE-TEXT %s
# BASE-HEADER: ImageBase: 0x280000000
# BASE-TEXT: Contents of section .text:
# BASE-TEXT-NEXT: 1000 00000080 02000000
@@ -48,6 +57,12 @@ symbols:
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: _DllMainCRTStartup
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: __ImageBase
Value: 0
SectionNumber: 0

View File

@@ -11,6 +11,9 @@ DEFAULT: SizeOfHeapCommit: 4096
# RUN: echo "HEAPSIZE 12288" > %t.def
# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
# RUN: echo "HEAPSIZE 0x3000" > %t.def
# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
CHECK1: SizeOfHeapReserve: 12288
CHECK1: SizeOfHeapCommit: 4096
@@ -20,6 +23,9 @@ CHECK1: SizeOfHeapCommit: 4096
# RUN: echo "HEAPSIZE 20480,12288" > %t.def
# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
# RUN: echo "HEAPSIZE 0x5000,0x3000" > %t.def
# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
CHECK2: SizeOfHeapReserve: 20480
CHECK2: SizeOfHeapCommit: 12288

View File

@@ -11,6 +11,9 @@ DEFAULT: SizeOfStackCommit: 4096
# RUN: echo "STACKSIZE 12288" > %t.def
# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
# RUN: echo "STACKSIZE 0x3000" > %t.def
# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
CHECK1: SizeOfStackReserve: 12288
CHECK1: SizeOfStackCommit: 4096
@@ -20,6 +23,9 @@ CHECK1: SizeOfStackCommit: 4096
# RUN: echo "STACKSIZE 20480,12288" > %t.def
# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
# RUN: echo "STACKSIZE 0x5000,0x3000" > %t.def
# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
CHECK2: SizeOfStackReserve: 20480
CHECK2: SizeOfStackCommit: 12288

View File

@@ -164,7 +164,7 @@ private:
Error readAsInt(uint64_t *I) {
read();
if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I))
if (Tok.K != Identifier || Tok.Value.getAsInteger(0, *I))
return createError("integer expected");
return Error::success();
}