aboutsummaryrefslogtreecommitdiff
path: root/ld
diff options
context:
space:
mode:
Diffstat (limited to 'ld')
-rw-r--r--ld/emultempl/emulation.em3
-rw-r--r--ld/emultempl/pe.em63
-rw-r--r--ld/emultempl/pep.em19
-rw-r--r--ld/ld.texi15
-rw-r--r--ld/ldemul.c8
-rw-r--r--ld/ldemul.h8
-rw-r--r--ld/ldlang.c37
-rw-r--r--ld/ldmain.c6
-rw-r--r--ld/ldmisc.c10
-rw-r--r--ld/testsuite/ld-aarch64/protections/bti-and-memory-seal-plt-1-a.d45
-rw-r--r--ld/testsuite/ld-aarch64/protections/bti-and-memory-seal-plt-1-b.d14
-rw-r--r--ld/testsuite/ld-aarch64/protections/bti-plt-1-b.d2
-rw-r--r--ld/testsuite/ld-plugin/lto.exp32
-rw-r--r--ld/testsuite/ld-plugin/pr32846a.c6
-rw-r--r--ld/testsuite/ld-plugin/pr32846b.c4
-rw-r--r--ld/testsuite/ld-plugin/pr32846c.c6
-rw-r--r--ld/testsuite/ld-plugin/pr32846d.c12
-rw-r--r--ld/testsuite/ld-plugin/pr32846e.c4
18 files changed, 242 insertions, 52 deletions
diff --git a/ld/emultempl/emulation.em b/ld/emultempl/emulation.em
index 7fe821a..8ff71d6 100644
--- a/ld/emultempl/emulation.em
+++ b/ld/emultempl/emulation.em
@@ -36,6 +36,7 @@ struct ld_emulation_xfer_struct ld_${EMULATION_NAME}_emulation =
${LDEMUL_EMIT_CTF_EARLY-NULL},
${LDEMUL_ACQUIRE_STRINGS_FOR_CTF-NULL},
${LDEMUL_NEW_DYNSYM_FOR_CTF-NULL},
- ${LDEMUL_PRINT_SYMBOL-NULL}
+ ${LDEMUL_PRINT_SYMBOL-NULL},
+ ${LDEMUL_FIND_START_SYMBOL-NULL}
};
EOF
diff --git a/ld/emultempl/pe.em b/ld/emultempl/pe.em
index 9a2b576..b522687 100644
--- a/ld/emultempl/pe.em
+++ b/ld/emultempl/pe.em
@@ -7,11 +7,11 @@ else
fi
case ${target} in
- *-*-cygwin*)
- cygwin_behavior=1
+ *-*-mingw*)
+ mingw_behavior=1
;;
*)
- cygwin_behavior=0;
+ mingw_behavior=0
;;
esac
@@ -126,9 +126,10 @@ fragment <<EOF
#define DEFAULT_PSEUDO_RELOC_VERSION 1
#endif
-#define DEFAULT_DLL_CHARACTERISTICS (${cygwin_behavior} ? 0 : \
- IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE \
- | IMAGE_DLL_CHARACTERISTICS_NX_COMPAT)
+#define DEFAULT_DLL_CHARACTERISTICS (${mingw_behavior} \
+ ? IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE \
+ | IMAGE_DLL_CHARACTERISTICS_NX_COMPAT \
+ : 0)
#if defined(TARGET_IS_i386pe) || ! defined(DLL_SUPPORT)
#define PE_DEF_SUBSYSTEM IMAGE_SUBSYSTEM_WINDOWS_CUI
@@ -2447,6 +2448,55 @@ gld${EMULATION_NAME}_find_potential_libraries
{
return ldfile_open_file_search (name, entry, "", ".lib");
}
+
+static struct bfd_link_hash_entry *
+gld${EMULATION_NAME}_find_alt_start_symbol
+ (struct bfd_sym_chain *entry)
+{
+#if defined (TARGET_IS_i386pe)
+ bool entry_has_stdcall_suffix;
+#endif
+ struct bfd_link_hash_entry *h;
+ size_t entry_name_len;
+ char *symbol_name;
+ const char *prefix;
+ const char *suffix;
+
+ entry_name_len = strlen (entry->name);
+
+ if (is_underscoring ())
+ prefix = "_";
+ else
+ prefix = "";
+
+#if defined (TARGET_IS_i386pe)
+ if ((entry_name_len > 2 && entry->name[entry_name_len-2] == '@' && ISDIGIT (entry->name[entry_name_len-1]))
+ || (entry_name_len > 3 && entry->name[entry_name_len-3] == '@' && ISDIGIT (entry->name[entry_name_len-2]) && ISDIGIT (entry->name[entry_name_len-1]))
+ || (entry_name_len > 4 && entry->name[entry_name_len-4] == '@' && ISDIGIT (entry->name[entry_name_len-3]) && ISDIGIT (entry->name[entry_name_len-2]) && ISDIGIT (entry->name[entry_name_len-1])))
+ entry_has_stdcall_suffix = true;
+ else
+ entry_has_stdcall_suffix = false;
+
+ if (!entry_has_stdcall_suffix && (bfd_link_dll (&link_info) || dll))
+ suffix = "@12";
+ else if (!entry_has_stdcall_suffix && pe_subsystem == 1 /* NT kernel driver */)
+ suffix = "@8";
+ else
+#endif
+ suffix = "";
+
+ if (*prefix == '\0' && *suffix == '\0')
+ return NULL;
+
+ symbol_name = xmalloc (entry_name_len + 5);
+ strcpy (symbol_name, prefix);
+ strcat (symbol_name, entry->name);
+ strcat (symbol_name, suffix);
+
+ h = bfd_link_hash_lookup (link_info.hash, symbol_name, false, false, true);
+ free (symbol_name);
+ return h;
+}
static char *
gld${EMULATION_NAME}_get_script (int *isfile)
@@ -2525,5 +2575,6 @@ LDEMUL_UNRECOGNIZED_FILE=gld${EMULATION_NAME}_unrecognized_file
LDEMUL_LIST_OPTIONS=gld${EMULATION_NAME}_list_options
LDEMUL_RECOGNIZED_FILE=gld${EMULATION_NAME}_recognized_file
LDEMUL_FIND_POTENTIAL_LIBRARIES=gld${EMULATION_NAME}_find_potential_libraries
+LDEMUL_FIND_START_SYMBOL=gld${EMULATION_NAME}_find_alt_start_symbol
source_em ${srcdir}/emultempl/emulation.em
diff --git a/ld/emultempl/pep.em b/ld/emultempl/pep.em
index 440c0bf..60a8339 100644
--- a/ld/emultempl/pep.em
+++ b/ld/emultempl/pep.em
@@ -9,11 +9,15 @@ fi
case ${target} in
*-*-cygwin*)
move_default_addr_high=1
- cygwin_behavior=1
+ mingw_behavior=0
+ ;;
+ *-*-mingw*)
+ move_default_addr_high=0
+ mingw_behavior=1
;;
*)
- move_default_addr_high=0;
- cygwin_behavior=0;
+ move_default_addr_high=0
+ mingw_behavior=0
;;
esac
@@ -126,10 +130,11 @@ fragment <<EOF
#define DLL_SUPPORT
#endif
-#define DEFAULT_DLL_CHARACTERISTICS (${cygwin_behavior} ? 0 : \
- IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE \
- | IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA \
- | IMAGE_DLL_CHARACTERISTICS_NX_COMPAT)
+#define DEFAULT_DLL_CHARACTERISTICS (${mingw_behavior} \
+ ? IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE \
+ | IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA \
+ | IMAGE_DLL_CHARACTERISTICS_NX_COMPAT \
+ : 0)
#if defined(TARGET_IS_i386pep) || defined(COFF_WITH_peAArch64) || ! defined(DLL_SUPPORT)
#define PE_DEF_SUBSYSTEM IMAGE_SUBSYSTEM_WINDOWS_CUI
diff --git a/ld/ld.texi b/ld/ld.texi
index 29bd0e1..ea4536a 100644
--- a/ld/ld.texi
+++ b/ld/ld.texi
@@ -531,7 +531,9 @@ named @var{entry}, the linker will try to parse @var{entry} as a number,
and use that as the entry address (the number will be interpreted in
base 10; you may use a leading @samp{0x} for base 16, or a leading
@samp{0} for base 8). @xref{Entry Point}, for a discussion of defaults
-and other ways of specifying the entry point.
+and other ways of specifying the entry point. For i386 PE, @var{entry}
+can be also the original function name (without the leading underscore
+and/or the trailing stdcall @samp{@@number} when applicable).
@kindex --exclude-libs
@item --exclude-libs @var{lib},@var{lib},...
@@ -3781,7 +3783,8 @@ of the PE file header:
@item --high-entropy-va
@itemx --disable-high-entropy-va
Image is compatible with 64-bit address space layout randomization
-(ASLR). This option is enabled by default for 64-bit PE images.
+(ASLR). This option is enabled by default for 64-bit PE images in
+MinGW targets.
This option also implies @option{--dynamicbase} and
@option{--enable-reloc-section}.
@@ -3791,9 +3794,9 @@ This option also implies @option{--dynamicbase} and
@itemx --disable-dynamicbase
The image base address may be relocated using address space layout
randomization (ASLR). This feature was introduced with MS Windows
-Vista for i386 PE targets. This option is enabled by default but
-can be disabled via the @option{--disable-dynamicbase} option.
-This option also implies @option{--enable-reloc-section}.
+Vista for i386 PE targets. This option is enabled by default for MinGW
+targets but can be disabled via the @option{--disable-dynamicbase}
+option. This option also implies @option{--enable-reloc-section}.
@kindex --forceinteg
@item --forceinteg
@@ -3806,7 +3809,7 @@ default.
@item --disable-nxcompat
The image is compatible with the Data Execution Prevention.
This feature was introduced with MS Windows XP SP2 for i386 PE
-targets. The option is enabled by default.
+targets. The option is enabled by default for MinGW targets.
@kindex --no-isolation
@item --no-isolation
diff --git a/ld/ldemul.c b/ld/ldemul.c
index dce0d38..35f91a2 100644
--- a/ld/ldemul.c
+++ b/ld/ldemul.c
@@ -35,6 +35,14 @@
static ld_emulation_xfer_type *ld_emulation;
+struct bfd_link_hash_entry *
+ldemul_find_alt_start_symbol (struct bfd_sym_chain *entry)
+{
+ if (ld_emulation->find_alt_start_symbol)
+ return ld_emulation->find_alt_start_symbol (entry);
+ return NULL;
+}
+
void
ldemul_hll (char *name)
{
diff --git a/ld/ldemul.h b/ld/ldemul.h
index aa014ae..c58d4c2 100644
--- a/ld/ldemul.h
+++ b/ld/ldemul.h
@@ -115,9 +115,10 @@ extern void ldemul_acquire_strings_for_ctf
(struct ctf_dict *, struct elf_strtab_hash *);
extern void ldemul_new_dynsym_for_ctf
(struct ctf_dict *, int symidx, struct elf_internal_sym *);
-
extern bool ldemul_print_symbol
(struct bfd_link_hash_entry *hash_entry, void *ptr);
+extern struct bfd_link_hash_entry * ldemul_find_alt_start_symbol
+ (struct bfd_sym_chain *);
typedef struct ld_emulation_xfer_struct {
/* Run before parsing the command line and script file.
@@ -259,6 +260,11 @@ typedef struct ld_emulation_xfer_struct {
bool (*print_symbol)
(struct bfd_link_hash_entry *hash_entry, void *ptr);
+ /* Called when ENTRY->name cannot be found by a direct lookup in INFO->hash.
+ Allows emulations to try variations of the name. */
+ struct bfd_link_hash_entry * (*find_alt_start_symbol)
+ (struct bfd_sym_chain *entry);
+
} ld_emulation_xfer_type;
typedef enum {
diff --git a/ld/ldlang.c b/ld/ldlang.c
index 0bb9e17..e036817 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -2486,11 +2486,18 @@ lang_map (void)
}
static bool
+is_defined (struct bfd_link_hash_entry *h)
+{
+ return h != NULL
+ && (h->type == bfd_link_hash_defined
+ || h->type == bfd_link_hash_defweak);
+}
+
+static bool
sort_def_symbol (struct bfd_link_hash_entry *hash_entry,
void *info ATTRIBUTE_UNUSED)
{
- if ((hash_entry->type == bfd_link_hash_defined
- || hash_entry->type == bfd_link_hash_defweak)
+ if (is_defined (hash_entry)
&& hash_entry->u.def.section->owner != link_info.output_bfd
&& hash_entry->u.def.section->owner != NULL)
{
@@ -4184,9 +4191,7 @@ ldlang_check_require_defined_symbols (void)
h = bfd_link_hash_lookup (link_info.hash, ptr->name,
false, false, true);
- if (h == NULL
- || (h->type != bfd_link_hash_defined
- && h->type != bfd_link_hash_defweak))
+ if (! is_defined (h))
einfo(_("%X%P: required symbol `%s' not defined\n"), ptr->name);
}
}
@@ -4892,9 +4897,7 @@ print_assignment (lang_assignment_statement_type *assignment,
h = bfd_link_hash_lookup (link_info.hash, assignment->exp->assign.dst,
false, false, true);
- if (h != NULL
- && (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak))
+ if (is_defined (h))
{
value = h->u.def.value;
value += h->u.def.section->output_section->vma;
@@ -4939,8 +4942,7 @@ print_one_symbol (struct bfd_link_hash_entry *hash_entry, void *ptr)
{
asection *sec = (asection *) ptr;
- if ((hash_entry->type == bfd_link_hash_defined
- || hash_entry->type == bfd_link_hash_defweak)
+ if (is_defined (hash_entry)
&& sec == hash_entry->u.def.section)
{
print_spaces (SECTION_NAME_MAP_LENGTH);
@@ -5062,7 +5064,8 @@ print_input_section (asection *i, bool is_discarded)
}
print_spaces (SECTION_NAME_MAP_LENGTH - len);
- if (i->output_section != NULL
+ if ((i->flags & SEC_EXCLUDE) == 0
+ && i->output_section != NULL
&& i->output_section->owner == link_info.output_bfd)
addr = i->output_section->vma + i->output_offset;
else
@@ -7233,9 +7236,7 @@ lang_end (void)
{
h = bfd_link_hash_lookup (link_info.hash, sym->name,
false, false, false);
- if (h != NULL
- && (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak)
+ if (is_defined (h)
&& !bfd_is_const_section (h->u.def.section))
break;
}
@@ -7254,9 +7255,11 @@ lang_end (void)
h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
false, false, true);
- if (h != NULL
- && (h->type == bfd_link_hash_defined
- || h->type == bfd_link_hash_defweak)
+
+ if (! is_defined (h) || h->u.def.section->output_section == NULL)
+ h = ldemul_find_alt_start_symbol (&entry_symbol);
+
+ if (is_defined (h)
&& h->u.def.section->output_section != NULL)
{
bfd_vma val;
diff --git a/ld/ldmain.c b/ld/ldmain.c
index 91237a4..67c60c3 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -423,8 +423,8 @@ ld_stop_phase (ld_phase phase)
if (pd->begin.ru_maxrss < usage.ru_maxrss)
pd->use.ru_maxrss += usage.ru_maxrss - pd->begin.ru_maxrss;
-#endif
}
+#endif
}
static void
@@ -563,8 +563,8 @@ report_phases (FILE * file, time_t * start, char ** argv)
COLUMN_ENTRY (pd->duration, "ld", 1);
#if defined (HAVE_GETRUSAGE)
COLUMN_ENTRY (pd->use.ru_maxrss, "ld", 2);
- COLUMN_ENTRY (pd->use.ru_utime.tv_sec, "ld", 3);
- COLUMN_ENTRY (pd->use.ru_stime.tv_sec, "ld", 4);
+ COLUMN_ENTRY ((int64_t) pd->use.ru_utime.tv_sec, PRId64, 3);
+ COLUMN_ENTRY ((int64_t) pd->use.ru_stime.tv_sec, PRId64, 4);
#endif
fprintf (file, "\n");
}
diff --git a/ld/ldmisc.c b/ld/ldmisc.c
index 9ee0781..3f305fa 100644
--- a/ld/ldmisc.c
+++ b/ld/ldmisc.c
@@ -42,7 +42,6 @@
%C clever filename:linenumber with function
%D like %C, but no function name
%E current bfd error or errno
- %F error is fatal
%G like %D, but only function name
%H like %C but in addition emit section+offset
%P print program name
@@ -70,7 +69,6 @@
void
vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning)
{
- bool isfatal = false;
const char *scan;
int arg_type;
unsigned int arg_count = 0;
@@ -280,11 +278,6 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning)
}
break;
- case 'F':
- /* Error is fatal. */
- isfatal = true;
- break;
-
case 'P':
/* Print program name. */
fprintf (fp, "%s", program_name);
@@ -586,9 +579,6 @@ vfinfo (FILE *fp, const char *fmt, va_list ap, bool is_warning)
if (is_warning && config.fatal_warnings)
config.make_executable = false;
-
- if (isfatal)
- xexit (1);
}
/* Format info message and print on stdout. */
diff --git a/ld/testsuite/ld-aarch64/protections/bti-and-memory-seal-plt-1-a.d b/ld/testsuite/ld-aarch64/protections/bti-and-memory-seal-plt-1-a.d
new file mode 100644
index 0000000..f8b1c21
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/protections/bti-and-memory-seal-plt-1-a.d
@@ -0,0 +1,45 @@
+#name: No '-z force-bti' with '-z memory-seal' with feature properties (BTI) forces the generation of BTI PLT (shared)
+#source: bti-plt-1.s
+#source: bti-plt-2.s
+#target: [check_shared_lib_support]
+#as: -mabi=lp64 -defsym __property_bti__=1
+#ld: -shared -z memory-seal -T bti-plt.ld -L./tmpdir -lbti-plt-so
+#objdump: -dr -j .plt
+
+[^:]*: *file format elf64-.*aarch64
+
+Disassembly of section \.plt:
+
+[0-9]+ <\.plt>:
+.*: d503245f bti c
+.*: a9bf7bf0 stp x16, x30, \[sp, #-16\]!
+.*: 90000090 adrp x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*: f9400e11 ldr x17, \[x16, #24\]
+.*: 91006210 add x16, x16, #0x18
+.*: d61f0220 br x17
+.*: d503201f nop
+.*: d503201f nop
+
+[0-9]+ <.*>:
+.*: 90000090 adrp x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*: f9401211 ldr x17, \[x16, #32\]
+.*: 91008210 add x16, x16, #0x20
+.*: d61f0220 br x17
+
+[0-9]+ <.*>:
+.*: 90000090 adrp x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*: f9401611 ldr x17, \[x16, #40\]
+.*: 9100a210 add x16, x16, #0x28
+.*: d61f0220 br x17
+
+[0-9]+ <.*>:
+.*: 90000090 adrp x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*: f9401a11 ldr x17, \[x16, #48\]
+.*: 9100c210 add x16, x16, #0x30
+.*: d61f0220 br x17
+
+[0-9]+ <.*>:
+.*: 90000090 adrp x16, 28000 <_GLOBAL_OFFSET_TABLE_>
+.*: f9401e11 ldr x17, \[x16, #56\]
+.*: 9100e210 add x16, x16, #0x38
+.*: d61f0220 br x17
diff --git a/ld/testsuite/ld-aarch64/protections/bti-and-memory-seal-plt-1-b.d b/ld/testsuite/ld-aarch64/protections/bti-and-memory-seal-plt-1-b.d
new file mode 100644
index 0000000..0dadcc9
--- /dev/null
+++ b/ld/testsuite/ld-aarch64/protections/bti-and-memory-seal-plt-1-b.d
@@ -0,0 +1,14 @@
+#name: No '-z force-bti' with '-z memory-seal' all input objects have BTI emits BTI feature (shared)
+#source: bti-plt-1.s
+#source: bti-plt-2.s
+#target: [check_shared_lib_support]
+#as: -mabi=lp64 -defsym __property_bti__=1
+#ld: -z memory-seal -shared -T bti-plt.ld
+#readelf: -n
+
+Displaying notes found in: .note.gnu.property
+[ ]+Owner[ ]+Data size[ ]+Description
+ GNU 0x00000018 NT_GNU_PROPERTY_TYPE_0
+ Properties: memory seal\s
+\s+AArch64 feature: BTI
+#pass
diff --git a/ld/testsuite/ld-aarch64/protections/bti-plt-1-b.d b/ld/testsuite/ld-aarch64/protections/bti-plt-1-b.d
index 1bf956c..4b0e424 100644
--- a/ld/testsuite/ld-aarch64/protections/bti-plt-1-b.d
+++ b/ld/testsuite/ld-aarch64/protections/bti-plt-1-b.d
@@ -2,7 +2,7 @@
#source: bti-plt-1.s
#target: [check_shared_lib_support]
#as: -mabi=lp64 -defsym __property_bti__=1
-#ld: -shared -z force-bti -T bti-plt.ld -L./tmpdir -lbti-plt-so
+#ld: -shared -T bti-plt.ld -L./tmpdir -lbti-plt-so
#objdump: -dr -j .plt
[^:]*: *file format elf64-.*aarch64
diff --git a/ld/testsuite/ld-plugin/lto.exp b/ld/testsuite/ld-plugin/lto.exp
index 9349190..3a56fb5 100644
--- a/ld/testsuite/ld-plugin/lto.exp
+++ b/ld/testsuite/ld-plugin/lto.exp
@@ -1212,6 +1212,38 @@ if { [is_elf_format] } {
if { [is_elf_format] && [check_lto_shared_available] } {
run_ld_link_exec_tests $lto_run_elf_shared_tests
+ if { [check_lto_fat_available] } {
+ run_cc_link_tests [list \
+ [list \
+ "Build libpr32846a.a" \
+ "$plug_opt" "-fPIC -O2 -flto $lto_no_fat" \
+ {pr32846a.c pr32846b.c} {} "libpr32846a.a" \
+ ] \
+ [list \
+ "Build libpr32846b.a" \
+ "$plug_opt" "-fPIC -O2 -flto $lto_no_fat" \
+ {pr32846a.c pr32846b.c pr32846c.c} {} "libpr32846b.a" \
+ ] \
+ [list \
+ "Build pr32846d.o" \
+ "$plug_opt" "-fPIC -O2 -flto $lto_no_fat" \
+ {pr32846d.c} {} \
+ ] \
+ [list \
+ "Build pr32846e.o" \
+ "$plug_opt" "-fPIC -O2 -flto $lto_no_fat" \
+ {pr32846e.c} {} \
+ ] \
+ [list \
+ "Build pr32846" \
+ "-shared -fPIC -O2 -flto $lto_no_fat -Wl,--no-undefined \
+ tmpdir/pr32846d.o tmpdir/libpr32846a.a \
+ tmpdir/libpr32846b.a tmpdir/pr32846e.o" \
+ "-O2 -fPIC -flto $lto_no_fat" \
+ {dummy.c} {} "pr32846" \
+ ] \
+ ] \
+ }
}
proc pr20103 {cflags libs} {
diff --git a/ld/testsuite/ld-plugin/pr32846a.c b/ld/testsuite/ld-plugin/pr32846a.c
new file mode 100644
index 0000000..8c16171
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846a.c
@@ -0,0 +1,6 @@
+extern void mkdir_p (void);
+void
+mkdir_parents (void)
+{
+ mkdir_p ();
+}
diff --git a/ld/testsuite/ld-plugin/pr32846b.c b/ld/testsuite/ld-plugin/pr32846b.c
new file mode 100644
index 0000000..9776a37
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846b.c
@@ -0,0 +1,4 @@
+void
+hash_new (void)
+{
+}
diff --git a/ld/testsuite/ld-plugin/pr32846c.c b/ld/testsuite/ld-plugin/pr32846c.c
new file mode 100644
index 0000000..f87cffb
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846c.c
@@ -0,0 +1,6 @@
+extern void hash_new (void);
+void
+kmod_new (void)
+{
+ hash_new();
+}
diff --git a/ld/testsuite/ld-plugin/pr32846d.c b/ld/testsuite/ld-plugin/pr32846d.c
new file mode 100644
index 0000000..c6f4102
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846d.c
@@ -0,0 +1,12 @@
+extern void kmod_new (void);
+extern void mkdir_parents (void);
+void
+do_lsmod (void)
+{
+ kmod_new ();
+}
+void
+do_static_nodes (void)
+{
+ mkdir_parents();
+}
diff --git a/ld/testsuite/ld-plugin/pr32846e.c b/ld/testsuite/ld-plugin/pr32846e.c
new file mode 100644
index 0000000..c4e5e56
--- /dev/null
+++ b/ld/testsuite/ld-plugin/pr32846e.c
@@ -0,0 +1,4 @@
+void
+mkdir_p (void)
+{
+}