Skip to contentSkip to conversation

Assign __gp to middle of short data sections

PATCH In review Keith Owens 3 participants 5 messages Aug 1, 2002

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Assign __gp to middle of short data sections

I was getting '__gp does not cover short data segment'. arch/ia64/vmlinus.lds.S assigns __gp well away from the short data sections, for no good reason that I can see. A kernel with more than 2^21 bytes between __gp and the end of sbss cannot link.

This patch (against 2.4.18) puts __gp right in the middle of the short data sections. The comment 'gp must be 16-byte aligned for exc. table' puzzles me, AFAICT the exception tables are not accessed via gp.

Index: 19-pre10.10/arch/ia64/vmlinux.lds.S

arch/ia64/vmlinux.lds.S Thu, 01 Aug 2002 13:09:02 +1000 kaos (linux-2.4/p/c/50_vmlinux.ld 1.1.5.1.2.1.1.1.1.2 644) renamed from arch/ia64/vmlinux.lds.S Thu, 09 May 2002 12:00:25 +1000 kaos (linux-2.4/p/c/50_vmlinux.ld 1.1.5.1.2.1.1.1.1.2 644) +2 -2
@@ -40,8 +40,6 @@ SECTIONS
 
   /* Read-only data */
 
-  __gp = ALIGN(16) + 0x200000;	/* gp must be 16-byte aligned for exc. table */
-
   /* Global data */
   _data = .;
 
@@ -130,6 +128,7 @@ SECTIONS
   .data : AT(ADDR(.data) - PAGE_OFFSET)
 	{ *(.data) *(.gnu.linkonce.d*) CONSTRUCTORS }
 
+  __got = ALIGN(16);
   .got : AT(ADDR(.got) - PAGE_OFFSET)
 	{ *(.got.plt) *(.got) }
   /* We want the small data sections together, so single-instruction offsets
@@ -141,6 +140,7 @@ SECTIONS
   _bss = .;
   .sbss : AT(ADDR(.sbss) - PAGE_OFFSET)
 	{ *(.sbss) *(.scommon) }
+  __gp = (. - (. - __got) / 2) & -16;	/* put __gp in the middle of the short data areas */
   .bss : AT(ADDR(.bss) - PAGE_OFFSET)
 	{ *(.bss) *(COMMON) }
   . = ALIGN(64 / 8);
#1 lore raw

RE: [Linux-ia64] [patch] Assign __gp to middle of short data sect

From: Keith Owens [mailto:[email protected]]

Quoted 8 lines

I was getting '__gp does not cover short data segment'. arch/ia64/vmlinus.lds.S assigns __gp well away from the short data sections, for no good reason that I can see. A kernel with more than 2^21 bytes between __gp and the end of sbss cannot link.

This patch (against 2.4.18) puts __gp right in the middle of the short data sections. The comment 'gp must be 16-byte aligned for exc. table' puzzles me, AFAICT the exception tables are not accessed via gp.

Look at include/asm-ia64/uaccess.h ... all the exception table entries use gp relative addressing.

-Tony

#2 lore raw
In reply to Keith Owens
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Keith Owens

Keith> I was getting '__gp does not cover short data segment'. Keith> arch/ia64/vmlinus.lds.S assigns __gp well away from the short Keith> data sections, for no good reason that I can see. A kernel Keith> with more than 2^21 bytes between __gp and the end of sbss Keith> cannot link.

Keith> This patch (against 2.4.18) puts __gp right in the middle of Keith> the short data sections.

Umh, the got must be covered by the __gp too!

The real problem that you were seeing is that the (old) linker script aligned __gp, but not the section it was pointing to. If the previous section ended on an address that was not 16-byte aligned, this would have the effect of putting the first word in the got out of reach. I fixed this bug a while ago (about two 2.4.18 patches ago, IIRC). The corrected version reads like this:

  . = ALIGN(16);
  __gp = . + 0x200000;	/* gp must be 16-byte aligned for exc. table */

Keith> The comment 'gp must be 16-byte
Keith> aligned for exc. table' puzzles me, AFAICT the exception Keith> tables are not accessed via gp.

The addresses in the exception table are currently gp-relative (so they fit in 32 bits), with the least-significant four bits reserved to encode extra info (such as slot number). If someone cares, this table probably could be converted to use IP-relative addresses, in which case this constraint could be dropped.

	--david
#3 lore raw
In reply to Keith Owens
Quoted 8 lines · David Mosberger
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line
Quoted 1 line · Keith Owens

Keith> I was getting '__gp does not cover short data segment'. Keith> arch/ia64/vmlinus.lds.S assigns __gp well away from the short Keith> data sections, for no good reason that I can see. A kernel Keith> with more than 2^21 bytes between __gp and the end of sbss Keith> cannot link.

Quoted 4 lines

Keith> This patch (against 2.4.18) puts __gp right in the middle of Keith> the short data sections.

Umh, the got must be covered by the __gp too!

@gprel() maps to instruction immediate22 which is a signed offset. My patch puts gp in the middle of the set { got, sdata, sbss }. ld is quite happy with that, it even tries to put gp in the middle of these sections if you have not already defined __gp.

Quoted 9 lines

The real problem that you were seeing is that the (old) linker script aligned __gp, but not the section it was pointing to. If the previous section ended on an address that was not 16-byte aligned, this would have the effect of putting the first word in the got out of reach. I fixed this bug a while ago (about two 2.4.18 patches ago, IIRC). The corrected version reads like this:

. = ALIGN(16);
__gp = . + 0x200000; /* gp must be 16-byte aligned for exc. table */

I tried that, same error, it is definitely a size problem. With my build, _data + 0x200000 (where __gp used to be) is e0000000049b7490, got starts at e000000004ced170, a difference from gp of 0x335ce0 bytes. imm22 can only do +/- 0x200000.

Quoted 9 lines

Keith> The comment 'gp must be 16-byte
Keith> aligned for exc. table' puzzles me, AFAICT the exception Keith> tables are not accessed via gp.

The addresses in the exception table are currently gp-relative (so they fit in 32 bits), with the least-significant four bits reserved to encode extra info (such as slot number). If someone cares, this table probably could be converted to use IP-relative addresses, in which case this constraint could be dropped.

In that case __ex_table should be moved to the same place as got, sdata, sbss. As it stands, the gprel data is split with all the read only data plus init code between them. ld does not detect errors for gprel in ex_table because __ex_table is not marked as short.

#4 lore raw
In reply to Keith Owens
Quoted 4 lines
Quoted 4 lines
Quoted 1 line
Quoted 1 line
Quoted 1 line · Keith Owens

. = ALIGN(16); __gp = . + 0x200000; /* gp must be 16-byte aligned for exc. table */

Keith> I tried that, same error, it is definitely a size problem. Keith> With my build, _data + 0x200000 (where __gp used to be) is Keith> e0000000049b7490, got starts at e000000004ced170, a Keith> difference from gp of 0x335ce0 bytes. imm22 can only do +/- Keith> 0x200000.

Please try with the latest 2.4.18 patch---__gp *is* defined after .data, not before.

Quoted 5 lines
Quoted 5 lines

The addresses in the exception table are currently gp-relative
(so they fit in 32 bits), with the least-significant four bits reserved to encode extra info (such as slot number). If someone cares, this table probably could be converted to use IP-relative addresses, in which case this constraint could be dropped.

Keith> In that case __ex_table should be moved to the same place as Keith> got, sdata, sbss. As it stands, the gprel data is split with Keith> all the read only data plus init code between them. ld does Keith> not detect errors for gprel in ex_table because __ex_table is Keith> not marked as short.

No, the gp-relative values in the exception table are 32-bits wide; there is no 22-bit limitation there.

	--david