[PATCH 19/32] x86/vdso2c: Align LOCAL symbols between vdso{-timens,}.so

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Align not only VDSO entries as on timens VDSO, but also addresses of
local functions. Otherwise, ld will put them after everything else
into *(.text*). That will result in common VDSO size bigger than
timens VDSO size (sic!).

Unfortunately, filtering by STB_WEAK doesn't work for ia32 VDSO:
by some reason gcc transforms weak symbols into local symbols in .so,
i.e.:
    27: 00000000   219 FUNC    WEAK   DEFAULT   12 clock_gettime
    29: 00000000    95 FUNC    WEAK   DEFAULT   14 gettimeofday
    32: 00000000    40 FUNC    WEAK   DEFAULT   16 time

become:
    20: 000006e0   219 FUNC    LOCAL  DEFAULT   12 clock_gettime
    31: 000007c0    95 FUNC    LOCAL  DEFAULT   12 gettimeofday
    33: 00000820    40 FUNC    LOCAL  DEFAULT   12 time

that results in the same align for two functions in .entries file:
		. = ABSOLUTE(0x6e0);
		*(.text.__vdso_clock_gettime*)
		. = ABSOLUTE(0x6e0);
		*(.text.clock_gettime*)

As result, ld becomes a very sad animal and refuses to cooperate:
ld:arch/x86/entry/vdso/vdso32/vdso32.lds:339 cannot move location counter backwards (from 0000000000000762 to 00000000000006e0)

Align local functions on VDSO to timens VDSO and filter weak functions
from .lds script.

Signed-off-by: Dmitry Safonov <dima@xxxxxxxxxx>
---
 arch/x86/entry/vdso/vdso2c.h | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/arch/x86/entry/vdso/vdso2c.h b/arch/x86/entry/vdso/vdso2c.h
index 50566dd94451..7096710140fe 100644
--- a/arch/x86/entry/vdso/vdso2c.h
+++ b/arch/x86/entry/vdso/vdso2c.h
@@ -15,7 +15,7 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
 	unsigned long mapping_size;
 	ELF(Ehdr) *hdr = (ELF(Ehdr) *)raw_addr;
 	unsigned int i, syms_nr;
-	unsigned long j;
+	unsigned long j, last_entry_addr;
 	ELF(Shdr) *symtab_hdr = NULL, *strtab_hdr, *secstrings_hdr,
 		*alt_sec = NULL;
 	ELF(Dyn) *dyn = 0, *dyn_end = 0;
@@ -121,7 +121,7 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
 		if (!out_entries_lds)
 			continue;
 
-		if (ELF_FUNC(ST_BIND, sym->st_info) != STB_GLOBAL)
+		if (ELF_FUNC(ST_BIND, sym->st_info) == STB_WEAK)
 			continue;
 
 		if (ELF_FUNC(ST_TYPE, sym->st_info) != STT_FUNC)
@@ -134,8 +134,19 @@ static void BITSFUNC(go)(void *raw_addr, size_t raw_len,
 
 	qsort(entries, next_entry - entries, sizeof(*entries), entry_addr_cmp);
 
+	last_entry_addr = -1UL;
 	while (next_entry != entries && out_entries_lds) {
 		next_entry--;
+
+		/*
+		 * Unfortunately, WEAK symbols from objects are resoved
+		 * into LOCAL symbols on ia32. Filter them here, as
+		 * linker wouldn't like aligning the same symbol twice.
+		 */
+		if (last_entry_addr == next_entry->addr)
+			continue;
+		last_entry_addr = next_entry->addr;
+
 		fprintf(out_entries_lds, "\t\t. = ABSOLUTE(%#lx);\n\t\t*(.text.%s*)\n",
 			next_entry->addr, next_entry->name);
 	}
-- 
2.20.1




[Index of Archives]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux