summaryrefslogtreecommitdiff
path: root/src/arbits
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2024-03-16 17:02:40 +0000
committermidipix <writeonce@midipix.org>2024-03-16 17:02:40 +0000
commit9f06b2ba383a2b998c010c4151b1dcbcbf3e2754 (patch)
tree93dffd57a71b806105e2fb715213c2e6100071a8 /src/arbits
parent1443ebb29f38c44a40bf3ce7754b9153b45712e9 (diff)
downloadslibtool-9f06b2ba383a2b998c010c4151b1dcbcbf3e2754.tar.bz2
slibtool-9f06b2ba383a2b998c010c4151b1dcbcbf3e2754.tar.xz
slbt_ar_create_dlsyms(): PE/COFF: properly set weak aliases of strong symbols.
Diffstat (limited to 'src/arbits')
-rw-r--r--src/arbits/slbt_archive_dlsyms.c110
1 files changed, 84 insertions, 26 deletions
diff --git a/src/arbits/slbt_archive_dlsyms.c b/src/arbits/slbt_archive_dlsyms.c
index dc60d12..942de3c 100644
--- a/src/arbits/slbt_archive_dlsyms.c
+++ b/src/arbits/slbt_archive_dlsyms.c
@@ -10,6 +10,36 @@
#include "slibtool_snprintf_impl.h"
#include "slibtool_errinfo_impl.h"
+static const char * slbt_strong_symname(
+ const char * symname,
+ bool fcoff,
+ char (*strbuf)[4096])
+{
+ const char * dot;
+ const char * mark;
+ char * sym;
+
+ if (fcoff) {
+ if (!strncmp(symname,"__imp_",6))
+ return 0;
+
+ if (strncmp(symname,".weak.",6))
+ return symname;
+
+ sym = *strbuf;
+ mark = &symname[6];
+ dot = strchr(mark,'.');
+
+ strncpy(sym,mark,dot-mark);
+ sym[dot-mark] = '\0';
+
+ return sym;
+ }
+
+ return symname;
+}
+
+
static int slbt_ar_dlsyms_define_by_type(
int fdout,
const char * arname,
@@ -17,27 +47,36 @@ static int slbt_ar_dlsyms_define_by_type(
const char * desc,
const char stype)
{
- uint64_t idx;
- uint64_t nsyms = 0;
+ uint64_t idx;
+ uint64_t nsyms;
+ bool fcoff;
+ const char * symname;
+ char strbuf[4096];
- for (idx=0; idx<mctx->armaps.armap_nsyms; idx++)
+ for (idx=0,nsyms=0; idx<mctx->armaps.armap_nsyms; idx++)
if (mctx->syminfv[idx]->ar_symbol_type[0] == stype)
nsyms++;
if (nsyms == 0)
return 0;
+ fcoff = slbt_host_objfmt_is_coff(mctx->dctx);
+ fcoff |= (mctx->ofmtattr & AR_OBJECT_ATTR_COFF);
+
if (slbt_dprintf(fdout,"/* %s (%s) */\n",desc,arname) < 0)
return SLBT_SYSTEM_ERROR(mctx->dctx,0);
for (idx=0; idx<mctx->armaps.armap_nsyms; idx++)
if (mctx->syminfv[idx]->ar_symbol_type[0] == stype)
- if (slbt_dprintf(fdout,
- (stype == 'T')
- ? "extern int %s();\n"
- : "extern char %s[];\n",
- mctx->syminfv[idx]->ar_symbol_name) < 0)
- return SLBT_SYSTEM_ERROR(mctx->dctx,0);
+ if ((symname = slbt_strong_symname(
+ mctx->syminfv[idx]->ar_symbol_name,
+ fcoff,&strbuf)))
+ if (slbt_dprintf(fdout,
+ (stype == 'T')
+ ? "extern int %s();\n"
+ : "extern char %s[];\n",
+ symname) < 0)
+ return SLBT_SYSTEM_ERROR(mctx->dctx,0);
if (slbt_dprintf(fdout,"\n") < 0)
return SLBT_SYSTEM_ERROR(mctx->dctx,0);
@@ -50,13 +89,22 @@ static int slbt_ar_dlsyms_get_max_len_by_type(
struct slbt_archive_meta_impl * mctx,
const char stype)
{
- int len;
- uint64_t idx;
+ int len;
+ uint64_t idx;
+ bool fcoff;
+ const char * symname;
+ char strbuf[4096];
+
+ fcoff = slbt_host_objfmt_is_coff(mctx->dctx);
+ fcoff |= (mctx->ofmtattr & AR_OBJECT_ATTR_COFF);
for (idx=0; idx<mctx->armaps.armap_nsyms; idx++)
if (mctx->syminfv[idx]->ar_symbol_type[0] == stype)
- if ((len = strlen(mctx->syminfv[idx]->ar_symbol_name)) > mlen)
- mlen = len;
+ if ((symname = slbt_strong_symname(
+ mctx->syminfv[idx]->ar_symbol_name,
+ fcoff,&strbuf)))
+ if ((len = strlen(symname)) > mlen)
+ mlen = len;
return mlen;
}
@@ -68,13 +116,18 @@ static int slbt_ar_dlsyms_add_by_type(
const char stype,
char (*namebuf)[4096])
{
- uint64_t idx;
- uint64_t nsyms;
- char * symname;
+ uint64_t idx;
+ uint64_t nsyms;
+ bool fcoff;
+ const char * symname;
+ char strbuf[4096];
nsyms = 0;
symname = *namebuf;
+ fcoff = slbt_host_objfmt_is_coff(mctx->dctx);
+ fcoff |= (mctx->ofmtattr & AR_OBJECT_ATTR_COFF);
+
for (idx=0; idx<mctx->armaps.armap_nsyms; idx++)
if (mctx->syminfv[idx]->ar_symbol_type[0] == stype)
nsyms++;
@@ -87,16 +140,21 @@ static int slbt_ar_dlsyms_add_by_type(
for (idx=0; idx<mctx->armaps.armap_nsyms; idx++) {
if (mctx->syminfv[idx]->ar_symbol_type[0] == stype) {
- if (slbt_snprintf(symname,sizeof(*namebuf),
- "%s\",",
- mctx->syminfv[idx]->ar_symbol_name) < 0)
- return SLBT_SYSTEM_ERROR(mctx->dctx,0);
-
- if (slbt_dprintf(fdout,fmt,
- symname,
- (stype == 'T') ? "&" : "",
- mctx->syminfv[idx]->ar_symbol_name) < 0)
- return SLBT_NESTED_ERROR(mctx->dctx);
+ symname = slbt_strong_symname(
+ mctx->syminfv[idx]->ar_symbol_name,
+ fcoff,&strbuf);
+
+ if (symname) {
+ if (slbt_snprintf(*namebuf,sizeof(*namebuf),
+ "%s\",",symname) < 0)
+ return SLBT_SYSTEM_ERROR(mctx->dctx,0);
+
+ if (slbt_dprintf(fdout,fmt,
+ *namebuf,
+ (stype == 'T') ? "&" : "",
+ symname) < 0)
+ return SLBT_NESTED_ERROR(mctx->dctx);
+ }
}
}