X-Git-Url: https://oss.titaniummirror.com/gitweb/?a=blobdiff_plain;f=debian%2Fpatches%2F203-hjl-binutils-indirect.dpatch;fp=debian%2Fpatches%2F203-hjl-binutils-indirect.dpatch;h=3d37bf7fc2f9466bf8f9681afb91cd92496d3fa2;hb=47f73751c91775676bb03af53e83c7f49dfda44f;hp=0000000000000000000000000000000000000000;hpb=6df9443a374e2b81278c61b8afc0a1eef7db280b;p=msp430-binutils.git diff --git a/debian/patches/203-hjl-binutils-indirect.dpatch b/debian/patches/203-hjl-binutils-indirect.dpatch new file mode 100755 index 0000000..3d37bf7 --- /dev/null +++ b/debian/patches/203-hjl-binutils-indirect.dpatch @@ -0,0 +1,573 @@ +#!/bin/sh -e +## 203-hjl-binutils-indirect.dpatch +## +## DP: Description: PR ld/3351; avoid linker crash on ia64 +## DP: Author: H.J. Lu +## DP: Upstream status: hjl 2.17.50.0.18 +## DP: Original patch: binutils-indirect-1.patch + +if [ $# -ne 1 ]; then + echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" + exit 1 +fi + +[ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts +patch_opts="${patch_opts:--f --no-backup-if-mismatch}" + +case "$1" in + -patch) patch $patch_opts -p1 < $0;; + -unpatch) patch $patch_opts -p1 -R < $0;; + *) + echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" + exit 1;; +esac + +exit 0 + +bfd/ + +2006-10-17 H.J. Lu + + 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. + +ld/testsuite/ + +2006-10-17 H.J. Lu + + 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. + +@DPATCH@ +diff -urNad binutils-2.18~cvs20070812~/bfd/elflink.c binutils-2.18~cvs20070812/bfd/elflink.c +--- binutils-2.18~cvs20070812~/bfd/elflink.c 2007-07-27 03:04:29.000000000 +0200 ++++ binutils-2.18~cvs20070812/bfd/elflink.c 2007-08-12 13:27:51.000000000 +0200 +@@ -823,6 +823,33 @@ + return dynsymcount; + } + ++/* 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 +@@ -851,6 +878,7 @@ + { + 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; +@@ -887,8 +915,9 @@ + if (info->hash->creator != abfd->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; +@@ -1047,23 +1076,11 @@ + /* 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 +@@ -1075,6 +1092,7 @@ + *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. + +@@ -1609,6 +1627,7 @@ + if (! dynamic) + { + if (info->shared ++ || hi->def_dynamic + || hi->ref_dynamic) + *dynsym = TRUE; + } +@@ -3737,6 +3756,7 @@ + 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; +@@ -4026,6 +4046,9 @@ + 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; +@@ -4232,22 +4255,36 @@ + } + else + h->def_regular = 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; +- if (h->def_regular +- || h->ref_regular +- || (h->u.weakdef != NULL +- && ! new_weakdef +- && h->u.weakdef->dynindx != -1)) ++ { ++ h->def_dynamic = 1; ++ hi->def_dynamic = 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; + } + +@@ -8396,6 +8433,10 @@ + 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: +@@ -8604,11 +8645,17 @@ + && !h->dynamic_weak + && ! elf_link_check_versioned_symbol (finfo->info, bed, h)) + { ++ 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; ++ + (*_bfd_error_handler) + (_("%B: %s symbol `%s' in %B is referenced by DSO"), + finfo->output_bfd, +- h->root.u.def.section == bfd_abs_section_ptr +- ? finfo->output_bfd : h->root.u.def.section->owner, ++ hi->root.u.def.section == bfd_abs_section_ptr ++ ? finfo->output_bfd : hi->root.u.def.section->owner, + ELF_ST_VISIBILITY (h->other) == STV_INTERNAL + ? "internal" + : ELF_ST_VISIBILITY (h->other) == STV_HIDDEN +@@ -8804,6 +8851,23 @@ + { + 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'"), ++ finfo->output_bfd, h->root.root.string); ++ eoinfo->failed = TRUE; ++ return FALSE; ++ } ++ } ++ + sym.st_name = h->dynstr_index; + esym = finfo->dynsym_sec->contents + h->dynindx * bed->s->sizeof_sym; + if (! check_dynsym (finfo->output_bfd, &sym)) +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect.exp binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect.exp +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect.exp 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect.exp 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,126 @@ ++# Expect script for various indirect symbol tests. ++# Copyright 2006 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: Nonrepresentable section on output" ++ ++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 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 +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1a.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1a.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1a.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1a.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,8 @@ ++extern void bar (void); ++ ++int ++start (void) ++{ ++ bar (); ++ return 0; ++} +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1b.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1b.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1b.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1b.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,6 @@ ++void ++foo (void) ++{ ++} ++ ++asm (".symver foo,foo@FOO"); +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1c.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1c.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect1c.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect1c.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,7 @@ ++extern void foo (void); ++ ++void ++bar (void) ++{ ++ foo (); ++} +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect2.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect2.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect2.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect2.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,9 @@ ++extern void foo (void); ++ ++asm (".symver foo,foo@@@FOO"); ++ ++void ++bar (void) ++{ ++ foo (); ++} +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3.out binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3.out +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3.out 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3.out 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,2 @@ ++MAIN ++DSO +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3a.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3a.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3a.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3a.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,10 @@ ++extern void bar (void); ++extern void foo (void); ++ ++int ++main (void) ++{ ++ foo (); ++ bar (); ++ return 0; ++} +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3b.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3b.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3b.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3b.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,9 @@ ++#include ++ ++void ++foo (void) ++{ ++ printf ("MAIN\n"); ++} ++ ++asm (".symver foo,foo@FOO"); +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3c.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3c.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect3c.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect3c.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,15 @@ ++#include ++ ++extern void foo (void); ++ ++void ++foo (void) ++{ ++ printf ("DSO\n"); ++} ++ ++void ++bar (void) ++{ ++ foo (); ++} +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4.out binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4.out +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4.out 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4.out 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,2 @@ ++MAIN2 ++MAIN2 +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4a.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4a.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4a.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4a.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,10 @@ ++extern void bar (void); ++extern void foo (void); ++ ++int ++main (void) ++{ ++ foo (); ++ bar (); ++ return 0; ++} +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4b.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4b.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4b.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4b.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,17 @@ ++#include ++ ++void ++foo2 (void) ++{ ++ printf ("MAIN2\n"); ++} ++ ++asm (".symver foo2,foo@@FOO2"); ++ ++void ++foo1 (void) ++{ ++ printf ("MAIN1\n"); ++} ++ ++asm (".symver foo1,foo@FOO1"); +diff -urNad binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4c.c binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4c.c +--- binutils-2.18~cvs20070812~/ld/testsuite/ld-elf/indirect4c.c 1970-01-01 01:00:00.000000000 +0100 ++++ binutils-2.18~cvs20070812/ld/testsuite/ld-elf/indirect4c.c 2007-08-12 13:27:51.000000000 +0200 +@@ -0,0 +1,15 @@ ++#include ++ ++extern void foo (void); ++ ++void ++foo (void) ++{ ++ printf ("DSO\n"); ++} ++ ++void ++bar (void) ++{ ++ foo (); ++}