// See comment in the MipsGotSection::writeTo.
size_t NewIndex = PageIndexMap.size() + 2;
auto P = PageIndexMap.insert(std::make_pair(EntryValue, NewIndex));
- assert(!P.second || PageIndexMap.size() <= PageEntriesNum);
+ assert(!P.second || PageIndexMap.size() <= (PageEntriesNum - 2));
return (uintX_t)P.first->second * sizeof(uintX_t);
}
size_t EntriesNum = TlsEntries.size();
// Take into account MIPS GOT header.
// See comment in the MipsGotSection::writeTo.
- PageEntriesNum += 2;
+ PageEntriesNum = 2;
for (const OutputSectionBase *OutSec : OutSections) {
// Calculate an upper bound of MIPS GOT entries required to store page
// addresses of local symbols. We assume the worst case - each 64kb
// page of the output section has at least one GOT relocation against it.
// Add 0x8000 to the section's size because the page address stored
// in the GOT entry is calculated as (value + 0x8000) & ~0xffff.
- PageEntriesNum += (OutSec->Size + 0x8000 + 0xfffe) / 0xffff;
+ PageEntriesNum += (OutSec->Size + 0xfffe) / 0xffff + 1;
}
EntriesNum += getLocalEntriesNum() + GlobalEntries.size();
Size = EntriesNum * sizeof(uintX_t);
# CHECK-NEXT: 20000: df 82 80 20 ld $2, -32736($gp)
# CHECK-NEXT: 20004: 64 42 00 18 daddiu $2, $2, 24
-# CHECK-NEXT: 20008: 24 42 80 38 addiu $2, $2, -32712
-# CHECK-NEXT: 2000c: 24 42 80 28 addiu $2, $2, -32728
-# CHECK-NEXT: 20010: 24 42 80 30 addiu $2, $2, -32720
+# CHECK-NEXT: 20008: 24 42 80 40 addiu $2, $2, -32704
+# CHECK-NEXT: 2000c: 24 42 80 30 addiu $2, $2, -32720
+# CHECK-NEXT: 20010: 24 42 80 38 addiu $2, $2, -32712
# CHECK: 0000000000020018 .text 00000000 foo
# CHECK: 0000000000037ff0 .got 00000000 .hidden _gp
# GOT-NEXT: Entry {
# GOT-NEXT: Address: 0x30018
# GOT-NEXT: Access: -32728
-# GOT-NEXT: Initial: 0x20014
+# GOT-NEXT: Initial: 0x0
# GOT-NEXT: }
# GOT-NEXT: Entry {
# GOT-NEXT: Address: 0x30020
# GOT-NEXT: Access: -32720
+# GOT-NEXT: Initial: 0x20014
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x30028
+# GOT-NEXT: Access: -32712
# GOT-NEXT: Initial: 0x20018
# GOT-NEXT: }
# GOT-NEXT: ]
# GOT-NEXT: Global entries [
# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x30028
-# GOT-NEXT: Access: -32712
+# GOT-NEXT: Address: 0x30030
+# GOT-NEXT: Access: -32704
# GOT-NEXT: Initial: 0x0
# GOT-NEXT: Value: 0x0
# GOT-NEXT: Type: Function
--- /dev/null
+# Check the case when small section (less that 0x10000 bytes) occupies
+# two adjacent 0xffff-bytes pages. We need to create two GOT entries
+# for R_MIPS_GOT_PAGE relocations.
+
+# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -o %t.o %s
+# RUN: ld.lld --section-start .rodata=0x27FFC -shared -o %t.so %t.o
+# RUN: llvm-readobj -t -mips-plt-got %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: Name: bar
+# CHECK-NEXT: Value: 0x28000
+# ^ page-address = (0x28000 + 0x8000) & ~0xffff = 0x30000
+
+# CHECK: Name: foo
+# CHECK-NEXT: Value: 0x27FFC
+# ^ page-address = (0x27ffc + 0x8000) & ~0xffff = 0x20000
+
+# CHECK: Local entries [
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Access: -32736
+# CHECK-NEXT: Initial: 0x20000
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Access: -32728
+# CHECK-NEXT: Initial: 0x30000
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+ .text
+ ld $v0,%got_page(foo)($gp)
+ ld $v0,%got_page(bar)($gp)
+
+ .rodata
+foo:
+ .word 0
+bar:
+ .word 0
# CHECK-NEXT: Entry {
# CHECK-NEXT: Address: 0x20010
# CHECK-NEXT: Access: -32736
+# CHECK-NEXT: Initial: 0x0
+# ^-- redundant
+# CHECK-NEXT: }
+# CHECK-NEXT: Entry {
+# CHECK-NEXT: Address: 0x20014
+# CHECK-NEXT: Access: -32732
# CHECK-NEXT: Initial: 0x40008
# ^-- glb1
# CHECK-NEXT: }
# CHECK-NEXT: 10014: 21 08 90 04 addi $8, $8, -28668
# CHECK-NEXT: 10018: 8f 88 80 20 lw $8, -32736($gp)
# CHECK-NEXT: 1001c: 21 08 10 04 addi $8, $8, 4100
-# CHECK-NEXT: 10020: 8f 88 80 28 lw $8, -32728($gp)
+# CHECK-NEXT: 10020: 8f 88 80 30 lw $8, -32720($gp)
# CHECK-NEXT: 10024: 21 08 10 08 addi $8, $8, 4104
-# CHECK-NEXT: 10028: 8f 88 80 2c lw $8, -32724($gp)
+# CHECK-NEXT: 10028: 8f 88 80 34 lw $8, -32716($gp)
#
# CHECK: SYMBOL TABLE:
# CHECK: 00051008 .data 00000000 .hidden bar
# GOT-NEXT: }
# GOT-NEXT: Entry {
# GOT-NEXT: Address: 0x20018
-# GOT-NEXT: Access: -327
+# GOT-NEXT: Access: -32728
+# GOT-NEXT: Initial: 0x0
+# ^-- redundant unused entry
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x2001C
+# GOT-NEXT: Access: -32724
+# GOT-NEXT: Initial: 0x0
+# ^-- redundant unused entry
+# GOT-NEXT: }
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address: 0x20020
+# GOT-NEXT: Access: -32720
# GOT-NEXT: Initial: 0x51008
# ^-- 'bar' address
# GOT-NEXT: }
# GOT-NEXT: ]
# GOT-NEXT: Global entries [
# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x2001C
-# GOT-NEXT: Access: -32724
+# GOT-NEXT: Address: 0x20024
+# GOT-NEXT: Access: -32716
# GOT-NEXT: Initial: 0x0
# GOT-NEXT: Value: 0x0
# GOT-NEXT: Type: None
# CHECK: Disassembly of section .text:
# CHECK-NEXT: __start:
# CHECK-NEXT: 20000: 3c 02 00 00 lui $2, 0
-# CHECK-NEXT: 20004: 8c 42 80 20 lw $2, -32736($2)
+# CHECK-NEXT: 20004: 8c 42 80 24 lw $2, -32732($2)
# CHECK-NEXT: 20008: 3c 02 00 00 lui $2, 0
-# CHECK-NEXT: 2000c: 8c 42 80 24 lw $2, -32732($2)
+# CHECK-NEXT: 2000c: 8c 42 80 28 lw $2, -32728($2)
#
# CHECK: bar:
-# CHECK-NEXT: 20010: 8c 42 80 1c lw $2, -32740($2)
+# CHECK-NEXT: 20010: 8c 42 80 20 lw $2, -32736($2)
# CHECK-NEXT: 20014: 8c 42 80 18 lw $2, -32744($2)
# CHECK-NEXT: 20018: 20 42 00 00 addi $2, $2, 0
# CHECK: Contents of section .got:
-# CHECK-NEXT: 30000 00000000 80000000 00040000 00020010
+# CHECK-NEXT: 30000 00000000 80000000 00040000 00000000
# ^ %hi(loc)
-# ^ %got(bar)
-# CHECK-NEXT: 30010 00020000 00040000
-# ^ %got_hi/lo(start)
-# ^ %got_hi/lo(loc)
+# ^ redundant entry
+# CHECK-NEXT: 30010 00020010 00020000 00040000
+# ^ %got(bar)
+# ^ %got_hi/lo(start)
+# ^ %got_hi/lo(loc)
# CHECK: 00040000 .data 00000000 loc
# CHECK: 00020000 .text 00000000 __start