Properly handle indirect symbols
2012-07-03 H.J. Lu <hongjiu.lu@intel.com> PR ld/3351 * elflink.c (_bfd_elf_update_dynamic_flags): New. (_bfd_elf_merge_symbol): Update both real and indirect symbol dynamic flags. (_bfd_elf_add_default_symbol): Make the real symbol dynamic if the indirect symbol is defined in a shared library. (elf_link_add_object_symbols): Likewise. If the indirect symbol has been forced local, don't make the real symbol dynamic. (elf_link_check_versioned_symbol): Check indirect symbol. (elf_link_output_extsym): Use real symbol definition when reporting indirect symbol error. Check version info for dynamic versioned symbol. 2012-07-03 H.J. Lu <hongjiu.lu@intel.com> PR ld/3351 * ld-elf/indirect.exp: New file. * ld-elf/indirect1a.c: Likewise. * ld-elf/indirect1b.c: Likewise. * ld-elf/indirect1c.c: Likewise. * ld-elf/indirect2.c: Likewise. * ld-elf/indirect3.out: Likewise. * ld-elf/indirect3a.c: Likewise. * ld-elf/indirect3b.c: Likewise. * ld-elf/indirect3c.c: Likewise. * ld-elf/indirect4.out: Likewise. * ld-elf/indirect4a.c: Likewise. * ld-elf/indirect4b.c: Likewise. * ld-elf/indirect4c.c: Likewise.
This commit is contained in:
parent
3146fac428
commit
90c984fc53
@ -1,3 +1,19 @@
|
||||
2012-07-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/3351
|
||||
* elflink.c (_bfd_elf_update_dynamic_flags): New.
|
||||
(_bfd_elf_merge_symbol): Update both real and indirect symbol
|
||||
dynamic flags.
|
||||
(_bfd_elf_add_default_symbol): Make the real symbol dynamic if
|
||||
the indirect symbol is defined in a shared library.
|
||||
(elf_link_add_object_symbols): Likewise. If the indirect
|
||||
symbol has been forced local, don't make the real symbol
|
||||
dynamic.
|
||||
(elf_link_check_versioned_symbol): Check indirect symbol.
|
||||
(elf_link_output_extsym): Use real symbol definition when
|
||||
reporting indirect symbol error. Check version info for
|
||||
dynamic versioned symbol.
|
||||
|
||||
2012-07-03 Alan Modra <amodra@gmail.com>
|
||||
|
||||
PR ld/14207
|
||||
|
120
bfd/elflink.c
120
bfd/elflink.c
@ -892,6 +892,33 @@ elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark if a symbol has a definition in a dynamic object or is
|
||||
weak in all dynamic objects. */
|
||||
|
||||
static void
|
||||
_bfd_elf_mark_dynamic_def_weak (struct elf_link_hash_entry *h,
|
||||
asection *sec, int bind)
|
||||
{
|
||||
if (!h->dynamic_def)
|
||||
{
|
||||
if (!bfd_is_und_section (sec))
|
||||
h->dynamic_def = 1;
|
||||
else
|
||||
{
|
||||
/* Check if this symbol is weak in all dynamic objects. If it
|
||||
is the first time we see it in a dynamic object, we mark
|
||||
if it is weak. Otherwise, we clear it. */
|
||||
if (!h->ref_dynamic)
|
||||
{
|
||||
if (bind == STB_WEAK)
|
||||
h->dynamic_weak = 1;
|
||||
}
|
||||
else if (bind != STB_WEAK)
|
||||
h->dynamic_weak = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* This function is called when we want to define a new symbol. It
|
||||
handles the various cases which arise when we find a definition in
|
||||
a dynamic object, or when there is already a definition in a
|
||||
@ -920,6 +947,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||
{
|
||||
asection *sec, *oldsec;
|
||||
struct elf_link_hash_entry *h;
|
||||
struct elf_link_hash_entry *hi;
|
||||
struct elf_link_hash_entry *flip;
|
||||
int bind;
|
||||
bfd *oldbfd;
|
||||
@ -958,8 +986,9 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||
if (!(*bed->relocs_compatible) (abfd->xvec, info->output_bfd->xvec))
|
||||
return TRUE;
|
||||
|
||||
/* For merging, we only care about real symbols. */
|
||||
|
||||
/* For merging, we only care about real symbols. But we need to make
|
||||
sure that indirect symbol dynamic flags are updated. */
|
||||
hi = h;
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
@ -1135,23 +1164,11 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||
/* We need to remember if a symbol has a definition in a dynamic
|
||||
object or is weak in all dynamic objects. Internal and hidden
|
||||
visibility will make it unavailable to dynamic objects. */
|
||||
if (newdyn && !h->dynamic_def)
|
||||
if (newdyn)
|
||||
{
|
||||
if (!bfd_is_und_section (sec))
|
||||
h->dynamic_def = 1;
|
||||
else
|
||||
{
|
||||
/* Check if this symbol is weak in all dynamic objects. If it
|
||||
is the first time we see it in a dynamic object, we mark
|
||||
if it is weak. Otherwise, we clear it. */
|
||||
if (!h->ref_dynamic)
|
||||
{
|
||||
if (bind == STB_WEAK)
|
||||
h->dynamic_weak = 1;
|
||||
}
|
||||
else if (bind != STB_WEAK)
|
||||
h->dynamic_weak = 0;
|
||||
}
|
||||
_bfd_elf_mark_dynamic_def_weak (h, sec, bind);
|
||||
if (h != hi)
|
||||
_bfd_elf_mark_dynamic_def_weak (hi, sec, bind);
|
||||
}
|
||||
|
||||
/* If the old symbol has non-default visibility, we ignore the new
|
||||
@ -1163,6 +1180,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
|
||||
*skip = TRUE;
|
||||
/* Make sure this symbol is dynamic. */
|
||||
h->ref_dynamic = 1;
|
||||
hi->ref_dynamic = 1;
|
||||
/* A protected symbol has external availability. Make sure it is
|
||||
recorded as dynamic.
|
||||
|
||||
@ -1723,6 +1741,7 @@ _bfd_elf_add_default_symbol (bfd *abfd,
|
||||
if (! dynamic)
|
||||
{
|
||||
if (! info->executable
|
||||
|| hi->def_dynamic
|
||||
|| hi->ref_dynamic)
|
||||
*dynsym = TRUE;
|
||||
}
|
||||
@ -3838,6 +3857,7 @@ error_free_dyn:
|
||||
flagword flags;
|
||||
const char *name;
|
||||
struct elf_link_hash_entry *h;
|
||||
struct elf_link_hash_entry *hi;
|
||||
bfd_boolean definition;
|
||||
bfd_boolean size_change_ok;
|
||||
bfd_boolean type_change_ok;
|
||||
@ -4170,6 +4190,9 @@ error_free_dyn:
|
||||
goto error_free_vers;
|
||||
|
||||
h = *sym_hash;
|
||||
/* We need to make sure that indirect symbol dynamic flags are
|
||||
updated. */
|
||||
hi = h;
|
||||
while (h->root.type == bfd_link_hash_indirect
|
||||
|| h->root.type == bfd_link_hash_warning)
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
@ -4358,25 +4381,38 @@ error_free_dyn:
|
||||
h->ref_dynamic = 1;
|
||||
}
|
||||
}
|
||||
if (! info->executable
|
||||
|| h->def_dynamic
|
||||
|| h->ref_dynamic)
|
||||
|
||||
/* If the indirect symbol has been forced local, don't
|
||||
make the real symbol dynamic. */
|
||||
if ((h == hi || !hi->forced_local)
|
||||
&& (! info->executable
|
||||
|| h->def_dynamic
|
||||
|| h->ref_dynamic))
|
||||
dynsym = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (! definition)
|
||||
h->ref_dynamic = 1;
|
||||
{
|
||||
h->ref_dynamic = 1;
|
||||
hi->ref_dynamic = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
h->def_dynamic = 1;
|
||||
h->dynamic_def = 1;
|
||||
hi->def_dynamic = 1;
|
||||
hi->dynamic_def = 1;
|
||||
}
|
||||
if (h->def_regular
|
||||
|| h->ref_regular
|
||||
|| (h->u.weakdef != NULL
|
||||
&& ! new_weakdef
|
||||
&& h->u.weakdef->dynindx != -1))
|
||||
|
||||
/* If the indirect symbol has been forced local, don't
|
||||
make the real symbol dynamic. */
|
||||
if ((h == hi || !hi->forced_local)
|
||||
&& (h->def_regular
|
||||
|| h->ref_regular
|
||||
|| (h->u.weakdef != NULL
|
||||
&& ! new_weakdef
|
||||
&& h->u.weakdef->dynindx != -1)))
|
||||
dynsym = TRUE;
|
||||
}
|
||||
|
||||
@ -8441,6 +8477,10 @@ elf_link_check_versioned_symbol (struct bfd_link_info *info,
|
||||
if (!is_elf_hash_table (info->hash))
|
||||
return FALSE;
|
||||
|
||||
/* Check indirect symbol. */
|
||||
while (h->root.type == bfd_link_hash_indirect)
|
||||
h = (struct elf_link_hash_entry *) h->root.u.i.link;
|
||||
|
||||
switch (h->root.type)
|
||||
{
|
||||
default:
|
||||
@ -8670,6 +8710,11 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
|
||||
{
|
||||
bfd *def_bfd;
|
||||
const char *msg;
|
||||
struct elf_link_hash_entry *hi = h;
|
||||
|
||||
/* Check indirect symbol. */
|
||||
while (hi->root.type == bfd_link_hash_indirect)
|
||||
hi = (struct elf_link_hash_entry *) hi->root.u.i.link;
|
||||
|
||||
if (ELF_ST_VISIBILITY (h->other) == STV_INTERNAL)
|
||||
msg = _("%B: internal symbol `%s' in %B is referenced by DSO");
|
||||
@ -8678,8 +8723,8 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
|
||||
else
|
||||
msg = _("%B: local symbol `%s' in %B is referenced by DSO");
|
||||
def_bfd = flinfo->output_bfd;
|
||||
if (h->root.u.def.section != bfd_abs_section_ptr)
|
||||
def_bfd = h->root.u.def.section->owner;
|
||||
if (hi->root.u.def.section != bfd_abs_section_ptr)
|
||||
def_bfd = hi->root.u.def.section->owner;
|
||||
(*_bfd_error_handler) (msg, flinfo->output_bfd, def_bfd,
|
||||
h->root.root.string);
|
||||
bfd_set_error (bfd_error_bad_value);
|
||||
@ -8929,6 +8974,23 @@ elf_link_output_extsym (struct bfd_hash_entry *bh, void *data)
|
||||
{
|
||||
bfd_byte *esym;
|
||||
|
||||
/* Since there is no version information in the dynamic string,
|
||||
if there is no version info in symbol version section, we will
|
||||
have a run-time problem. */
|
||||
if (h->verinfo.verdef == NULL)
|
||||
{
|
||||
char *p = strrchr (h->root.root.string, ELF_VER_CHR);
|
||||
|
||||
if (p && p [1] != '\0')
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B: No symbol version section for versioned symbol `%s'"),
|
||||
flinfo->output_bfd, h->root.root.string);
|
||||
eoinfo->failed = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
sym.st_name = h->dynstr_index;
|
||||
esym = flinfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym;
|
||||
if (!check_dynsym (flinfo->output_bfd, &sym))
|
||||
|
@ -1,3 +1,20 @@
|
||||
2012-07-03 H.J. Lu <hongjiu.lu@intel.com>
|
||||
|
||||
PR ld/3351
|
||||
* ld-elf/indirect.exp: New file.
|
||||
* ld-elf/indirect1a.c: Likewise.
|
||||
* ld-elf/indirect1b.c: Likewise.
|
||||
* ld-elf/indirect1c.c: Likewise.
|
||||
* ld-elf/indirect2.c: Likewise.
|
||||
* ld-elf/indirect3.out: Likewise.
|
||||
* ld-elf/indirect3a.c: Likewise.
|
||||
* ld-elf/indirect3b.c: Likewise.
|
||||
* ld-elf/indirect3c.c: Likewise.
|
||||
* ld-elf/indirect4.out: Likewise.
|
||||
* ld-elf/indirect4a.c: Likewise.
|
||||
* ld-elf/indirect4b.c: Likewise.
|
||||
* ld-elf/indirect4c.c: Likewise.
|
||||
|
||||
2012-07-02 Roland McGrath <mcgrathr@google.com>
|
||||
|
||||
* ld/testsuite/ld-i386/tlsbin-nacl.rd: Update for symbol table changes.
|
||||
|
126
ld/testsuite/ld-elf/indirect.exp
Normal file
126
ld/testsuite/ld-elf/indirect.exp
Normal file
@ -0,0 +1,126 @@
|
||||
# Expect script for various indirect symbol tests.
|
||||
# Copyright 2012 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
#
|
||||
|
||||
#
|
||||
# Written by H.J. Lu (hongjiu.lu@intel.com)
|
||||
#
|
||||
|
||||
# Exclude non-ELF targets.
|
||||
|
||||
if ![is_elf_format] {
|
||||
return
|
||||
}
|
||||
|
||||
# Check if compiler works
|
||||
if { [which $CC] == 0 } {
|
||||
return
|
||||
}
|
||||
|
||||
proc check_link_message { cmd string testname } {
|
||||
send_log "$cmd\n"
|
||||
verbose "$cmd"
|
||||
catch "exec $cmd" exec_output
|
||||
send_log "$exec_output\n"
|
||||
verbose "$exec_output"
|
||||
|
||||
foreach str $string {
|
||||
if [string match "*$str*" $exec_output] {
|
||||
pass "$testname: $str"
|
||||
} else {
|
||||
fail "$testname: $str"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if { ![ld_compile $CC $srcdir/$subdir/indirect1a.c tmpdir/indirect1a.o]
|
||||
|| ![ld_compile $CC $srcdir/$subdir/indirect1b.c tmpdir/indirect1b.o]
|
||||
|| ![ld_compile "$CC -fPIC" $srcdir/$subdir/indirect2.c tmpdir/indirect2.o]
|
||||
|| ![ld_compile $CC $srcdir/$subdir/indirect3a.c tmpdir/indirect3a.o]
|
||||
|| ![ld_compile $CC $srcdir/$subdir/indirect3b.c tmpdir/indirect3b.o]
|
||||
|| ![ld_compile $CC $srcdir/$subdir/indirect4a.c tmpdir/indirect4a.o]
|
||||
|| ![ld_compile $CC $srcdir/$subdir/indirect4b.c tmpdir/indirect4b.o] } {
|
||||
unresolved "Indirect symbol tests"
|
||||
return
|
||||
}
|
||||
|
||||
set build_tests {
|
||||
{"Build libindirect1c.so"
|
||||
"-shared" "-fPIC"
|
||||
{indirect1c.c} {} "libindirect1c.so"}
|
||||
{"Build libindirect3c.so"
|
||||
"-shared" "-fPIC"
|
||||
{indirect3c.c} {} "libindirect3c.so"}
|
||||
{"Build libindirect4c.so"
|
||||
"-shared" "-fPIC"
|
||||
{indirect4c.c} {} "libindirect4c.so"}
|
||||
}
|
||||
|
||||
run_cc_link_tests $build_tests
|
||||
|
||||
global ld
|
||||
|
||||
set string ": final link failed: Bad value"
|
||||
set string1 ": local symbol \`foo\' in tmpdir/indirect1b.o is referenced by DSO"
|
||||
|
||||
set testname "Indirect symbol 1a"
|
||||
set cmd "$ld -e start -o tmpdir/indirect1 tmpdir/indirect1a.o tmpdir/indirect1b.o tmpdir/libindirect1c.so"
|
||||
check_link_message "$cmd" [list $string1 $string] "$testname"
|
||||
|
||||
set testname "Indirect symbol 1b"
|
||||
set cmd "$ld -e start -o tmpdir/indirect1 tmpdir/indirect1a.o tmpdir/libindirect1c.so tmpdir/indirect1b.o"
|
||||
check_link_message "$cmd" [list $string1 $string] "$testname"
|
||||
|
||||
set string ": final link failed: Nonrepresentable section on output"
|
||||
set string2 ": No symbol version section for versioned symbol \`foo@FOO\'"
|
||||
set testname "Indirect symbol 2"
|
||||
set cmd "$ld -shared -o tmpdir/indirect2.so tmpdir/indirect2.o"
|
||||
check_link_message "$cmd" [list $string2 $string] "$testname"
|
||||
|
||||
# The following tests require running the executable generated by ld.
|
||||
if ![isnative] {
|
||||
return
|
||||
}
|
||||
|
||||
set run_tests {
|
||||
{"Run with libindirect3c.so 1"
|
||||
"tmpdir/indirect3a.o tmpdir/indirect3b.o tmpdir/libindirect3c.so" ""
|
||||
{dummy.c} "indirect3a" "indirect3.out"}
|
||||
{"Run with libindirect3c.so 2"
|
||||
"tmpdir/indirect3a.o tmpdir/libindirect3c.so tmpdir/indirect3b.o" ""
|
||||
{dummy.c} "indirect3b" "indirect3.out"}
|
||||
{"Run with libindirect3c.so 3"
|
||||
"tmpdir/indirect3b.o tmpdir/libindirect3c.so tmpdir/indirect3a.o" ""
|
||||
{dummy.c} "indirect3c" "indirect3.out"}
|
||||
{"Run with libindirect3c.so 4"
|
||||
"tmpdir/libindirect3c.so tmpdir/indirect3b.o tmpdir/indirect3a.o" ""
|
||||
{dummy.c} "indirect3d" "indirect3.out"}
|
||||
{"Run with libindirect4c.so 1"
|
||||
"tmpdir/indirect4a.o tmpdir/indirect4b.o tmpdir/libindirect4c.so" ""
|
||||
{dummy.c} "indirect4a" "indirect4.out"}
|
||||
{"Run with libindirect4c.so 2"
|
||||
"tmpdir/indirect4a.o tmpdir/libindirect4c.so tmpdir/indirect4b.o" ""
|
||||
{dummy.c} "indirect4b" "indirect4.out"}
|
||||
{"Run with libindirect4c.so 3"
|
||||
"tmpdir/indirect4b.o tmpdir/libindirect4c.so tmpdir/indirect4a.o" ""
|
||||
{dummy.c} "indirect4c" "indirect4.out"}
|
||||
{"Run with libindirect4c.so 4"
|
||||
"tmpdir/libindirect4c.so tmpdir/indirect4b.o tmpdir/indirect4a.o" ""
|
||||
{dummy.c} "indirect4d" "indirect4.out"}
|
||||
}
|
||||
|
||||
run_ld_link_exec_tests [] $run_tests
|
8
ld/testsuite/ld-elf/indirect1a.c
Normal file
8
ld/testsuite/ld-elf/indirect1a.c
Normal file
@ -0,0 +1,8 @@
|
||||
extern void bar (void);
|
||||
|
||||
int
|
||||
start (void)
|
||||
{
|
||||
bar ();
|
||||
return 0;
|
||||
}
|
6
ld/testsuite/ld-elf/indirect1b.c
Normal file
6
ld/testsuite/ld-elf/indirect1b.c
Normal file
@ -0,0 +1,6 @@
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
}
|
||||
|
||||
asm (".symver foo,foo@FOO");
|
7
ld/testsuite/ld-elf/indirect1c.c
Normal file
7
ld/testsuite/ld-elf/indirect1c.c
Normal file
@ -0,0 +1,7 @@
|
||||
extern void foo (void);
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
foo ();
|
||||
}
|
9
ld/testsuite/ld-elf/indirect2.c
Normal file
9
ld/testsuite/ld-elf/indirect2.c
Normal file
@ -0,0 +1,9 @@
|
||||
extern void foo (void);
|
||||
|
||||
asm (".symver foo,foo@@@FOO");
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
foo ();
|
||||
}
|
2
ld/testsuite/ld-elf/indirect3.out
Normal file
2
ld/testsuite/ld-elf/indirect3.out
Normal file
@ -0,0 +1,2 @@
|
||||
MAIN
|
||||
DSO
|
10
ld/testsuite/ld-elf/indirect3a.c
Normal file
10
ld/testsuite/ld-elf/indirect3a.c
Normal file
@ -0,0 +1,10 @@
|
||||
extern void bar (void);
|
||||
extern void foo (void);
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
foo ();
|
||||
bar ();
|
||||
return 0;
|
||||
}
|
9
ld/testsuite/ld-elf/indirect3b.c
Normal file
9
ld/testsuite/ld-elf/indirect3b.c
Normal file
@ -0,0 +1,9 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
printf ("MAIN\n");
|
||||
}
|
||||
|
||||
asm (".symver foo,foo@FOO");
|
15
ld/testsuite/ld-elf/indirect3c.c
Normal file
15
ld/testsuite/ld-elf/indirect3c.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
extern void foo (void);
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
printf ("DSO\n");
|
||||
}
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
foo ();
|
||||
}
|
2
ld/testsuite/ld-elf/indirect4.out
Normal file
2
ld/testsuite/ld-elf/indirect4.out
Normal file
@ -0,0 +1,2 @@
|
||||
MAIN2
|
||||
MAIN2
|
10
ld/testsuite/ld-elf/indirect4a.c
Normal file
10
ld/testsuite/ld-elf/indirect4a.c
Normal file
@ -0,0 +1,10 @@
|
||||
extern void bar (void);
|
||||
extern void foo (void);
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
foo ();
|
||||
bar ();
|
||||
return 0;
|
||||
}
|
17
ld/testsuite/ld-elf/indirect4b.c
Normal file
17
ld/testsuite/ld-elf/indirect4b.c
Normal file
@ -0,0 +1,17 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void
|
||||
foo2 (void)
|
||||
{
|
||||
printf ("MAIN2\n");
|
||||
}
|
||||
|
||||
asm (".symver foo2,foo@@FOO2");
|
||||
|
||||
void
|
||||
foo1 (void)
|
||||
{
|
||||
printf ("MAIN1\n");
|
||||
}
|
||||
|
||||
asm (".symver foo1,foo@FOO1");
|
15
ld/testsuite/ld-elf/indirect4c.c
Normal file
15
ld/testsuite/ld-elf/indirect4c.c
Normal file
@ -0,0 +1,15 @@
|
||||
#include <stdio.h>
|
||||
|
||||
extern void foo (void);
|
||||
|
||||
void
|
||||
foo (void)
|
||||
{
|
||||
printf ("DSO\n");
|
||||
}
|
||||
|
||||
void
|
||||
bar (void)
|
||||
{
|
||||
foo ();
|
||||
}
|
Loading…
Reference in New Issue
Block a user