This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
[PATCH] SEGV whilst placing sections
- From: Mark Shinwell <shinwell at codesourcery dot com>
- To: binutils at sourceware dot org
- Date: Tue, 20 Jun 2006 15:08:52 +0100
- Subject: [PATCH] SEGV whilst placing sections
The following C code, when compiled for an ARM target with -fexceptions
and linked using the attached linker script, causes SEGV in
lang_insert_orphan () when placing the .ARM.extab section.
int f(int *);
int g(void)
{
int a;
return f(&a);
}
In this case, the "after" parameter to lang_insert_orphan () corresponds
to the .rodata section, the last in the linked list of "asection"s.
The upshot is that place->section points at the "next" entry of the final
section in the list, .rodata. This "next" pointer is NULL, so "as" ends up
NULL, and we fault when "as->prev" is computed.
The attached patch fixes this problem, and doesn't cause any test
failures -- but I'm not 100% sure this is the correct thing to do.
Perhaps someone who knows the code could tell me if they think this is
reasonable?
Thanks,
Mark
--
ld/ChangeLog:
2006-06-20 Mark Shinwell <shinwell@codesourcery.com>
* ldlang.c (lang_insert_orphan): Correctly handle the case where
the section is to end up after the section currently at the end
of the list in output_bfd.
Index: ld/ldlang.c
===================================================================
RCS file: /cvs/src/src/ld/ldlang.c,v
retrieving revision 1.224
diff -U3 -p -r1.224 ldlang.c
--- ld/ldlang.c 20 Jun 2006 02:22:14 -0000 1.224
+++ ld/ldlang.c 20 Jun 2006 13:36:35 -0000
@@ -1445,7 +1445,18 @@ lang_insert_orphan (asection *s,
place->section = &output_bfd->sections;
as = *place->section;
- if (as != snew && as->prev != snew)
+
+ if (!as)
+ {
+ /* Put the section at the end of the list. */
+
+ /* Unlink the section. */
+ bfd_section_list_remove (output_bfd, snew);
+
+ /* Now tack it back on in the right place. */
+ bfd_section_list_append (output_bfd, snew);
+ }
+ else if (as != snew && as->prev != snew)
{
/* Unlink the section. */
bfd_section_list_remove (output_bfd, snew);
OUTPUT_ARCH(arm)
ENTRY(stext)
jiffies = jiffies_64;
SECTIONS
{
. = (0xc0000000) + 0x00008000;
.init : { /* Init code and data */
_stext = .;
_sinittext = .;
*(.init.text)
_einittext = .;
__proc_info_begin = .;
*(.proc.info.init)
__proc_info_end = .;
__arch_info_begin = .;
*(.arch.info.init)
__arch_info_end = .;
__tagtable_begin = .;
*(.taglist.init)
__tagtable_end = .;
. = ALIGN(16);
__setup_start = .;
*(.init.setup)
__setup_end = .;
__early_begin = .;
*(.early_param.init)
__early_end = .;
__initcall_start = .;
*(.initcall1.init)
*(.initcall2.init)
*(.initcall3.init)
*(.initcall4.init)
*(.initcall5.init)
*(.initcall6.init)
*(.initcall7.init)
__initcall_end = .;
__con_initcall_start = .;
*(.con_initcall.init)
__con_initcall_end = .;
__security_initcall_start = .;
*(.security_initcall.init)
__security_initcall_end = .;
. = ALIGN(32);
__initramfs_end = .;
. = ALIGN(64);
__per_cpu_start = .;
*(.data.percpu)
__per_cpu_end = .;
__init_begin = _stext;
*(.init.data)
. = ALIGN(4096);
__init_end = .;
}
/DISCARD/ : { /* Exit code and data */
*(.exit.text)
*(.exit.data)
*(.exitcall.exit)
}
.text : { /* Real text segment */
_text = .; /* Text and read-only data */
*(.text)
. = ALIGN(8); __sched_text_start = .; *(.sched.text) __sched_text_end = .;
. = ALIGN(8); __lock_text_start = .; *(.spinlock.text) __lock_text_end = .;
*(.fixup)
*(.gnu.warning)
*(.rodata)
*(.rodata.*)
*(.glue_7)
*(.glue_7t)
*(.got) /* Global offset table */
}
. = ALIGN(4096); __start_rodata = .; .rodata : AT(ADDR(.rodata) - 0) { *(.rodata) *(.rodata.*) *(__vermagic) } .rodata1 : AT(ADDR(.rodata1) - 0) { *(.rodata1) } .pci_fixup : AT(ADDR(.pci_fixup) - 0) { __start_pci_fixups_early = .; *(.pci_fixup_early) __end_pci_fixups_early = .; __start_pci_fixups_header = .; *(.pci_fixup_header) __end_pci_fixups_header = .; __start_pci_fixups_final = .; *(.pci_fixup_final) __end_pci_fixups_final = .; __start_pci_fixups_enable = .; *(.pci_fixup_enable) __end_pci_fixups_enable = .; } .rio_route : AT(ADDR(.rio_route) - 0) { __start_rio_route_ops = .; *(.rio_route_ops) __end_rio_route_ops = .; } __ksymtab : AT(ADDR(__ksymtab) - 0) { __start___ksymtab = .; *(__ksymtab) __stop___ksymtab = .; } __ksymtab_gpl : AT(ADDR(__ksymtab_gpl) - 0) { __start___ksymtab_gpl = .; *(__ksymtab_gpl) __stop___ksymtab_gpl = .; } __ksymtab_gpl_future : AT(ADDR(__ksymtab_gpl_future) - 0) { __start___ksymtab_gpl_future = .; *(__ksymtab_gpl_future) __stop___ksymtab_gpl_future = .; } __kcrctab : AT(ADDR(__kcrctab) - 0) { __start___kcrctab = .; *(__kcrctab) __stop___kcrctab = .; } __kcrctab_gpl : AT(ADDR(__kcrctab_gpl) - 0) { __start___kcrctab_gpl = .; *(__kcrctab_gpl) __stop___kcrctab_gpl = .; } __kcrctab_gpl_future : AT(ADDR(__kcrctab_gpl_future) - 0) { __start___kcrctab_gpl_future = .; *(__kcrctab_gpl_future) __stop___kcrctab_gpl_future = .; } __ksymtab_strings : AT(ADDR(__ksymtab_strings) - 0) { *(__ksymtab_strings) } __end_rodata = .; . = ALIGN(4096); __param : AT(ADDR(__param) - 0) { __start___param = .; *(__param) __stop___param = .; }
_etext = .; /* End of text and rodata section */
. = ALIGN(8192);
__data_loc = .;
.data : AT(__data_loc) {
__data_start = .; /* address in memory */
/*
* first, the init task union, aligned
* to an 8192 byte boundary.
*/
*(.init.task)
. = ALIGN(4096);
__nosave_begin = .;
*(.data.nosave)
. = ALIGN(4096);
__nosave_end = .;
/*
* then the cacheline aligned data
*/
. = ALIGN(32);
*(.data.cacheline_aligned)
/*
* The exception fixup table (might need resorting at runtime)
*/
. = ALIGN(32);
__start___ex_table = .;
*(__ex_table)
__stop___ex_table = .;
/*
* and the usual data section
*/
*(.data)
CONSTRUCTORS
_edata = .;
}
.bss : {
__bss_start = .; /* BSS */
*(.bss)
*(COMMON)
_end = .;
}
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
}
/*
* These must never be empty
* If you have to comment these two assert statements out, your
* binutils is too old (for other reasons as well)
*/
ASSERT((__proc_info_end - __proc_info_begin), "missing CPU support")
ASSERT((__arch_info_end - __arch_info_begin), "no machine record defined")