DEFINE: %{local1a_386} = 0x3000 DEFINE: %{sym1_386} = 0x20B0 DEFINE: %{sym3_386} = 0x20BC DEFINE: %{local1a_x64} = 0x3000 DEFINE: %{sym1_x64} = 0x20E8 DEFINE: %{sym3_x64} = 0x20D8 DEFINE: %{relocbegin} = 8 DEFINE: %{relocend} = 80 DEFINE: %{rdatasize} = 254 RUN: yaml2obj -o %t.exe-x86_64 %p/Inputs/pseudoreloc.x86_64.yaml RUN: llvm-readobj %t.exe-x86_64 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=CHECK,CHECK-X64 --match-full-lines --implicit-check-not=warning \ RUN: -D#WORD=8 -D#SYM1=%{sym1_x64} -D#SYM3=%{sym3_x64} -D#LOCAL1A=%{local1a_x64} -DPREFIX= RUN: yaml2obj -o %t.exe-i386 %p/Inputs/pseudoreloc.i386.yaml RUN: llvm-readobj %t.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=CHECK,CHECK-386 --match-full-lines --implicit-check-not=warning \ RUN: -D#WORD=4 -D#SYM1=%{sym1_386} -D#SYM3=%{sym3_386} -D#LOCAL1A=%{local1a_386} -DPREFIX=_ CHECK-X64: Format: COFF-x86-64 CHECK-X64-NEXT: Arch: x86_64 CHECK-386: Format: COFF-i386 CHECK-386-NEXT: Arch: i386 CHECK-NEXT: AddressSize: [[#%u,BW:mul(WORD,8)]]bit CHECK-NEXT: PseudoReloc [ CHECK-NEXT: Entry { CHECK-NEXT: Symbol: 0x[[#%X,SYM1]] CHECK-NEXT: SymbolName: sym1 CHECK-NEXT: Target: 0x[[#%X,LOCAL1A]] CHECK-NEXT: TargetSymbol: .data+0x0 CHECK-NEXT: BitWidth: [[#BW]] CHECK-NEXT: } CHECK-NEXT: Entry { CHECK-NEXT: Symbol: 0x[[#%X,SYM1+mul(1,WORD)]] CHECK-NEXT: SymbolName: sym2 CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(1,WORD)]] CHECK-NEXT: TargetSymbol: [[PREFIX]]local2a CHECK-NEXT: BitWidth: [[#BW]] CHECK-NEXT: } CHECK-NEXT: Entry { CHECK-NEXT: Symbol: 0x[[#%X,SYM3]] CHECK-NEXT: SymbolName: sym3 CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(2,WORD)]] CHECK-NEXT: TargetSymbol: [[PREFIX]]local3a CHECK-NEXT: BitWidth: [[#BW]] CHECK-NEXT: } CHECK-NEXT: Entry { CHECK-NEXT: Symbol: 0x[[#%X,SYM3]] CHECK-NEXT: SymbolName: sym3 CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(3,WORD)]] CHECK-NEXT: TargetSymbol: [[PREFIX]]local3a+0x[[#%X,mul(1,WORD)]] CHECK-NEXT: BitWidth: [[#BW]] CHECK-NEXT: } CHECK-NEXT: Entry { CHECK-NEXT: Symbol: 0x[[#%X,SYM1]] CHECK-NEXT: SymbolName: sym1 CHECK-NEXT: Target: 0x[[#%X,LOCAL1A+mul(4,WORD)]] CHECK-NEXT: TargetSymbol: [[PREFIX]]local3a+0x[[#%X,mul(2,WORD)]] CHECK-NEXT: BitWidth: [[#BW]] CHECK-NEXT: } CHECK-NEXT: ] ; Test that llvm-readobj warns about missing imported symbol names. RUN: yaml2obj -o %t.corrupted-iat.exe-i386 %p/Inputs/pseudoreloc.i386.yaml \ RUN: -DSYMBOL0=30000000 -DSYMBOL1=B2200000 -DSYMBOL2=00FFFF00 RUN: llvm-readobj %t.corrupted-iat.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefix=INVALIDSYMBOL --match-full-lines -D#LOCAL1A=%{local1a_386} --implicit-check-not=warning INVALIDSYMBOL: Symbol: 0x[[#%X,ADDR:0x0030]] INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the address referenced by pseudo-relocation is not a valid import entry: 0x[[#%x,ADDR]] INVALIDSYMBOL-NEXT: SymbolName: (missing) INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A]] INVALIDSYMBOL: Symbol: 0x[[#%X,ADDR:0x20B2]] INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the address referenced by pseudo-relocation is not a valid import entry: 0x[[#%x,ADDR]] INVALIDSYMBOL-NEXT: SymbolName: (missing) INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+4]] INVALIDSYMBOL: Symbol: 0x[[#%X,ADDR:0xFFFF00]] INVALIDSYMBOL-NEXT: {{.*}}warning: {{.*}}: the address referenced by pseudo-relocation is not a valid import entry: 0x[[#%x,ADDR]] INVALIDSYMBOL-NEXT: SymbolName: (missing) INVALIDSYMBOL-NEXT: Target: 0x[[#%X,LOCAL1A+8]] ; Assume the position of the section and the relocation list for further tests. RUN: FileCheck --input-file=%p/Inputs/pseudoreloc.i386.yaml %s --check-prefix=RELOCPOS --match-full-lines \ RUN: -D#RDATASIZE=%{rdatasize} -DTHEBEGIN=%{relocbegin} -DTHEEND=%{relocend} RELOCPOS: sections: RELOCPOS-NOT: - Name: RELOCPOS: - Name: .text RELOCPOS-NOT: - Name: RELOCPOS: - Name: .rdata RELOCPOS-NEXT: Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] RELOCPOS-NEXT: VirtualAddress: 8192 RELOCPOS-NEXT: VirtualSize: [[#%d,RDATASIZE]] RELOCPOS: - Name: .data RELOCPOS-NEXT: Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] RELOCPOS-NEXT: VirtualAddress: 12288 RELOCPOS: - Name: ___RUNTIME_PSEUDO_RELOC_LIST_END__ RELOCPOS-NEXT: Value: [{{\[}}END=[[THEEND]]{{]}}] RELOCPOS: - Name: ___RUNTIME_PSEUDO_RELOC_LIST__ RELOCPOS-NEXT: Value: [{{\[}}BEGIN=[[THEBEGIN]]{{]}}] RELOCPOS-NEXT: SectionNumber: {{\[\[SECTION_OF_BEGIN=2\]\]}} ; Test that llvm-readobj warns if a symbol belongs to a nonexistent section. RUN: yaml2obj -o %t.nosection.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DSECTION_OF_LOCAL2A=999 RUN: llvm-readobj %t.nosection.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=WARN-NOSECTION --match-full-lines WARN-NOSECTION: {{.*}} warning:{{.*}}: section index out of bounds ; Test that llvm-readobj shows an empty list if the relocation list has no contents. RUN: yaml2obj -o %t.empty-list.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DEND=20 RUN: llvm-readobj %t.empty-list.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefix=EMPTY --match-full-lines --implicit-check-not=warning ; Test that llvm-readobj shows an empty list if the relocation list has no header. RUN: yaml2obj -o %t.no-header.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DEND=%{relocbegin} RUN: llvm-readobj %t.no-header.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefix=EMPTY --match-full-lines --implicit-check-not=warning ; Test that llvm-readobj shows an empty list if the image is stripped. RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/imports.exe.coff-i386 2>&1 | \ RUN: FileCheck %s --check-prefix=EMPTY --match-full-lines --implicit-check-not=warning ; Test that llvm-readobj warns if the marker symbol of the relocation list is absent from the symbol table. RUN: sed -e 's/__RUNTIME//' %p/Inputs/pseudoreloc.i386.yaml | \ RUN: yaml2obj -o %t.nosymbol.exe-i386 RUN: llvm-readobj %t.nosymbol.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=EMPTY,WARN-MISSINGMARKER --match-full-lines ; Test that llvm-readobj shows an empty list if a .obj is specified. RUN: llvm-readobj --coff-pseudoreloc %p/Inputs/trivial.obj.coff-i386 2>&1 | \ RUN: FileCheck %s --check-prefix=EMPTY --match-full-lines --implicit-check-not=warning ; Test that llvm-readobj warns if the header of the relocation list is broken. RUN: yaml2obj -o %t.broken-header.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DBEGIN=1%{relocbegin} RUN: llvm-readobj %t.broken-header.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=EMPTY,WARN-INVALIDHEADER --match-full-lines ; Test that llvm-readobj warns if end < start. RUN: yaml2obj -o %t.negative-size.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DBEGIN=%{relocend} -DEND=%{relocbegin} RUN: llvm-readobj %t.negative-size.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=EMPTY,WARN-LOWEREND -D#BEGIN=%{relocend} -D#END=%{relocbegin} --match-full-lines ; Test that llvm-readobj warns if the marker symbol points out of the section space. RUN: yaml2obj -o %t.outofrange-both.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DBEGIN=8888 -DEND=9999 RUN: llvm-readobj %t.outofrange-both.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=EMPTY,WARN-OUTOFRANGE --match-full-lines -D#RDATASIZE=%{rdatasize} RUN: yaml2obj -o %t.outofrange-end.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DEND=8888 RUN: llvm-readobj %t.outofrange-end.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=EMPTY,WARN-OUTOFRANGE --match-full-lines -D#RDATASIZE=%{rdatasize} ; Test that llvm-readobj warns if the marker symbols point different sections. RUN: yaml2obj -o %t.section-differs.exe-i386 %p/Inputs/pseudoreloc.i386.yaml -DSECTION_OF_BEGIN=1 RUN: llvm-readobj %t.section-differs.exe-i386 --coff-pseudoreloc 2>&1 | \ RUN: FileCheck %s --check-prefixes=EMPTY,WARN-SECTIONDIFFERS --match-full-lines EMPTY: Format: COFF-i386 EMPTY-NEXT: Arch: i386 EMPTY-NEXT: AddressSize: 32bit EMPTY-NEXT: PseudoReloc [ WARN-MISSINGMARKER-NEXT: {{.*}}warning: {{.*}}: the marker symbols for runtime pseudo-relocation were not found WARN-INVALIDHEADER-NEXT: {{.*}}warning: {{.*}}: invalid runtime pseudo-relocation records WARN-LOWEREND-NEXT: {{.*}}warning: {{.*}}: the end marker symbol for runtime pseudo-relocation must point to a higher address than where the begin marker points to: expected >=0x[[#%x,BEGIN]], but got 0x[[#%x,END]] WARN-OUTOFRANGE-NEXT: {{.*}}warning: {{.*}}: the marker symbol of runtime pseudo-relocation points past the end of the section 0x[[#%x,RDATASIZE]]: got 0x[[#%x,8888]] WARN-SECTIONDIFFERS-NEXT: {{.*}}warning: {{.*}}: the end marker symbol for runtime pseudo-relocation must point to the same section where the begin marker points to: expected 1, but got {{[2-9]}} EMPTY-NEXT: ] ;; ;; To regenerate Inputs/pseudoreloc.*.yaml, run following one-liner and review actual address map: ;; ;; $ split-file pseudoreloc.test /tmp/pseudoreloc && bash /tmp/pseudoreloc/generate.sh && cp /tmp/pseudoreloc/*.yaml Inputs/ ;; #--- generate.sh cd "$(dirname $0)" set -e generate() { LANG=C local arch=$1 local emul=$2 llc -mtriple $arch-mingw32 -filetype obj export1.ll -o export1.$arch.o ld.lld -m $emul --dll export1.$arch.o -o export1.$arch.dll -entry= llc -mtriple $arch-mingw32 -filetype obj export2.ll -o export2.$arch.o ld.lld -m $emul --dll export2.$arch.o -o export2.$arch.dll -entry= llc -mtriple $arch-mingw32 -filetype obj import.ll -o import.$arch.o ld.lld -m $emul -S import.$arch.o export1.$arch.dll export2.$arch.dll -o pseudoreloc.$arch.exe -entry=start \ --disable-dynamicbase --disable-reloc-section obj2yaml pseudoreloc.$arch.exe -o pseudoreloc.$arch.yaml.orig llvm-readobj --coff-imports --syms --section-headers pseudoreloc.$arch.exe > dump.$arch.txt local begin=$(sed -n -e '/__RUNTIME_PSEUDO_RELOC_LIST__/,/Value:/{/Value:/{s/ *Value: *//p;q}}' dump.$arch.txt) # Make these parameterizable: # - the referenced symbol in 1st, 2nd, and 3rd relocation entry # - the marker symbols' value # - a section which the marker symbol belongs to # - a section which the symbol of the relocation target belongs to sed -E -f - pseudoreloc.$arch.yaml.orig < pseudoreloc.$arch.yaml /- Name: *\\.rdata/,/SectionData:/{ s/( *SectionData: *[0-9A-F]{$(($begin * 2 + 24))})(.{8})(.{16})(.{8})(.{16})(.{8})/\\1[[SYMBOL0=\\2]]\\3[[SYMBOL1=\\4]]\\5[[SYMBOL2=\\6]]/ } /__RUNTIME_PSEUDO_RELOC_LIST_END__/,/Value:/{ /Value:/s/([0-9]+)/[[END=\1]]/ } /__RUNTIME_PSEUDO_RELOC_LIST__/,/Value:/{ /Value:/s/([0-9]+)/[[BEGIN=\1]]/ } /__RUNTIME_PSEUDO_RELOC_LIST__/,/SectionNumber:/{ /SectionNumber:/s/([0-9]+)/[[SECTION_OF_BEGIN=\1]]/ } /local2a/,/SectionNumber:/{ /SectionNumber:/s/([0-9]+)/[[SECTION_OF_LOCAL2A=\1]]/ } EOT # Ensure the binaries generated from the parameterized yaml and original one are exactly the same. diff <(yaml2obj pseudoreloc.$arch.yaml.orig -o -) <(yaml2obj pseudoreloc.$arch.yaml -o -) } generate i386 i386pe generate x86_64 i386pep #--- export1.ll @sym1 = dso_local dllexport global [4 x i8] c"\11\22\33\44" @sym2 = dso_local dllexport global [4 x i8] c"\55\66\77\88" #--- export2.ll @sym3 = dso_local dllexport global [4 x i8] c"\AA\BB\CC\DD" #--- import.ll @__RUNTIME_PSEUDO_RELOC_LIST__ = external dso_local constant ptr @__RUNTIME_PSEUDO_RELOC_LIST_END__ = external dso_local constant ptr @sym1 = external dso_local global [4 x i8] @sym2 = external dso_local global [4 x i8] @sym3 = external dso_local global [4 x i8] @dummy_to_bump_address = private constant i64 u0x4488226655117733 @local1a = private global ptr getelementptr (i8, ptr @sym1, i32 1) @local2a = dso_local global ptr getelementptr (i8, ptr @sym2, i32 2) @local3a = dso_local global [2 x ptr] [ptr getelementptr (i8, ptr @sym3, i32 1), ptr getelementptr (i8, ptr @sym3, i32 1)] @local1b = private global ptr getelementptr (i8, ptr @sym1, i32 2) define dso_local i32 @start() noinline nounwind { %p1a = load ptr, ptr @local1a %v1a = load i8, ptr %p1a %x1a = sext i8 %v1a to i32 %p2a = load ptr, ptr @local2a %v2a = load i8, ptr %p2a %x2a = sext i8 %v2a to i32 %p3a = load ptr, ptr @local3a %v3a = load i8, ptr %p3a %x3a = sext i8 %v3a to i32 %p1b = load ptr, ptr @local1b %v1b = load i8, ptr %p1b %x1b = sext i8 %v1b to i32 %1 = add nsw i32 %x1a, %x2a %2 = add nsw i32 %x3a, %x1b %3 = add nsw i32 %1, %2 ret i32 %3 } define dso_local i32 @_pei386_runtime_relocator() noinline nounwind { %1 = load ptr, ptr @__RUNTIME_PSEUDO_RELOC_LIST_END__ %2 = load ptr, ptr @__RUNTIME_PSEUDO_RELOC_LIST__ %3 = ptrtoint ptr %1 to i64 %4 = ptrtoint ptr %2 to i64 %5 = sub i64 %3, %4 %6 = trunc i64 %5 to i32 ret i32 %6 }