|
|
db49af |
/*******************************************************************/
|
|
|
db49af |
/* slibtool: a skinny libtool implementation, written in C */
|
|
|
db49af |
/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
|
|
|
db49af |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
db49af |
/*******************************************************************/
|
|
|
db49af |
|
|
|
db49af |
#include <time.h>
|
|
|
db49af |
#include <stdio.h>
|
|
|
db49af |
#include <stdint.h>
|
|
|
db49af |
#include <stddef.h>
|
|
|
db49af |
#include <stdlib.h>
|
|
|
db49af |
#include <string.h>
|
|
|
db49af |
#include <inttypes.h>
|
|
|
db49af |
#include <sys/mman.h>
|
|
|
db49af |
#include <sys/types.h>
|
|
|
db49af |
|
|
|
db49af |
#include <slibtool/slibtool.h>
|
|
|
db49af |
#include <slibtool/slibtool_arbits.h>
|
|
|
db49af |
#include "slibtool_ar_impl.h"
|
|
|
db49af |
#include "slibtool_driver_impl.h"
|
|
|
db49af |
#include "slibtool_errinfo_impl.h"
|
|
|
db49af |
|
|
|
db49af |
/* anonymous fun */
|
|
|
db49af |
#ifndef MAP_ANONYMOUS
|
|
|
db49af |
#define MAP_ANONYMOUS MAP_ANON
|
|
|
db49af |
#endif
|
|
|
db49af |
|
|
|
db49af |
/* time stamp format specifier */
|
|
|
db49af |
#define PPRII64 "%"PRIi64
|
|
|
db49af |
|
|
|
db49af |
/* file size format specifier */
|
|
|
db49af |
#define PPRIU64 "%"PRIu64
|
|
|
db49af |
|
|
|
e06cc0 |
/* dlopen self/force */
|
|
|
e06cc0 |
static const char slbt_ar_self_dlunit[] = "@PROGRAM@";
|
|
|
e06cc0 |
|
|
|
db49af |
struct armap_buffer_32 {
|
|
|
db49af |
uint32_t moffset;
|
|
|
db49af |
const char * symname;
|
|
|
db49af |
uint32_t baseidx;
|
|
|
db49af |
};
|
|
|
db49af |
|
|
|
db49af |
struct armap_buffer_64 {
|
|
|
db49af |
uint64_t moffset;
|
|
|
db49af |
const char * symname;
|
|
|
db49af |
uint64_t baseidx;
|
|
|
db49af |
};
|
|
|
db49af |
|
|
|
db49af |
static const char ar_signature[] = AR_SIGNATURE;
|
|
|
db49af |
|
|
|
db49af |
static int slbt_create_anonymous_archive_ctx(
|
|
|
db49af |
const struct slbt_driver_ctx * dctx,
|
|
|
db49af |
size_t size,
|
|
|
db49af |
struct slbt_archive_ctx ** pctx)
|
|
|
db49af |
{
|
|
|
db49af |
struct slbt_archive_ctx_impl * ctx;
|
|
|
db49af |
|
|
|
db49af |
if (!(ctx = calloc(1,sizeof(*ctx))))
|
|
|
db49af |
return SLBT_BUFFER_ERROR(dctx);
|
|
|
db49af |
|
|
|
db49af |
ctx->map.map_size = size;
|
|
|
db49af |
ctx->map.map_addr = mmap(
|
|
|
db49af |
0,size,
|
|
|
db49af |
PROT_READ|PROT_WRITE,
|
|
|
db49af |
MAP_PRIVATE|MAP_ANONYMOUS,
|
|
|
db49af |
-1,0);
|
|
|
db49af |
|
|
|
db49af |
if (ctx->map.map_addr == MAP_FAILED) {
|
|
|
db49af |
free(ctx);
|
|
|
db49af |
return SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
ctx->dctx = dctx;
|
|
|
db49af |
ctx->actx.map = &ctx->map;
|
|
|
db49af |
|
|
|
db49af |
*pctx = &ctx->actx;
|
|
|
db49af |
|
|
|
db49af |
return 0;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
static off_t slbt_armap_write_be_32(unsigned char * mark, uint32_t val)
|
|
|
db49af |
{
|
|
|
db49af |
mark[0] = val >> 24;
|
|
|
db49af |
mark[1] = val >> 16;
|
|
|
db49af |
mark[2] = val >> 8;
|
|
|
db49af |
mark[3] = val;
|
|
|
db49af |
|
|
|
db49af |
return sizeof(uint32_t);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
static off_t slbt_armap_write_le_32(unsigned char * mark, uint32_t val)
|
|
|
db49af |
{
|
|
|
db49af |
mark[0] = val;
|
|
|
db49af |
mark[1] = val >> 8;
|
|
|
db49af |
mark[2] = val >> 16;
|
|
|
db49af |
mark[3] = val >> 24;
|
|
|
db49af |
|
|
|
db49af |
return sizeof(uint32_t);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
static off_t slbt_armap_write_be_64(unsigned char * mark, uint64_t val)
|
|
|
db49af |
{
|
|
|
db49af |
slbt_armap_write_be_32(&mark[0],val >> 32);
|
|
|
db49af |
slbt_armap_write_be_32(&mark[4],val);
|
|
|
db49af |
|
|
|
db49af |
return sizeof(uint64_t);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
static off_t slbt_armap_write_le_64(unsigned char * mark, uint64_t val)
|
|
|
db49af |
{
|
|
|
db49af |
slbt_armap_write_be_32(&mark[0],val);
|
|
|
db49af |
slbt_armap_write_be_32(&mark[4],val >> 32);
|
|
|
db49af |
|
|
|
db49af |
return sizeof(uint64_t);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
|
|
|
51c276 |
static int slbt_ar_merge_archives_fail(
|
|
|
db49af |
struct slbt_archive_ctx * arctx,
|
|
|
db49af |
struct armap_buffer_32 * bsdmap32,
|
|
|
db49af |
struct armap_buffer_64 * bsdmap64,
|
|
|
db49af |
int ret)
|
|
|
db49af |
{
|
|
|
db49af |
if (bsdmap32)
|
|
|
db49af |
free(bsdmap32);
|
|
|
db49af |
|
|
|
db49af |
if (bsdmap64)
|
|
|
db49af |
free(bsdmap64);
|
|
|
db49af |
|
|
|
db49af |
if (arctx)
|
|
|
51c276 |
slbt_ar_free_archive_ctx(arctx);
|
|
|
db49af |
|
|
|
db49af |
return ret;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
|
|
|
51c276 |
int slbt_ar_merge_archives(
|
|
|
db49af |
struct slbt_archive_ctx * const arctxv[],
|
|
|
db49af |
struct slbt_archive_ctx ** arctxm)
|
|
|
db49af |
{
|
|
|
db49af |
struct slbt_archive_ctx * const * arctxp;
|
|
|
db49af |
struct slbt_archive_ctx * arctx;
|
|
|
db49af |
|
|
|
db49af |
const struct slbt_driver_ctx * dctx;
|
|
|
db49af |
const struct slbt_archive_meta * meta;
|
|
|
db49af |
|
|
|
db49af |
struct ar_raw_file_header * arhdr;
|
|
|
db49af |
struct ar_meta_member_info ** memberp;
|
|
|
db49af |
struct ar_meta_member_info * meminfo;
|
|
|
db49af |
|
|
|
db49af |
struct ar_meta_member_info * armap;
|
|
|
db49af |
struct ar_meta_member_info * arnames;
|
|
|
db49af |
|
|
|
db49af |
const struct ar_meta_armap_common_32 * armap32;
|
|
|
db49af |
const struct ar_meta_armap_common_64 * armap64;
|
|
|
db49af |
const struct ar_meta_armap_ref_32 * symref32;
|
|
|
db49af |
const struct ar_meta_armap_ref_64 * symref64;
|
|
|
db49af |
|
|
|
db49af |
struct armap_buffer_32 * bsdmap32;
|
|
|
db49af |
struct armap_buffer_64 * bsdmap64;
|
|
|
db49af |
struct armap_buffer_32 * bsdsort32;
|
|
|
db49af |
struct armap_buffer_64 * bsdsort64;
|
|
|
db49af |
|
|
|
db49af |
size_t nbytes;
|
|
|
db49af |
ssize_t nwritten;
|
|
|
db49af |
|
|
|
db49af |
uint32_t mapattr;
|
|
|
db49af |
uint64_t nmembers;
|
|
|
db49af |
uint64_t nsymrefs;
|
|
|
db49af |
|
|
|
db49af |
uint64_t sarmap;
|
|
|
db49af |
uint64_t sarname;
|
|
|
db49af |
uint64_t sarchive;
|
|
|
db49af |
uint64_t smembers;
|
|
|
db49af |
uint64_t ssymrefs;
|
|
|
db49af |
uint64_t ssymstrs;
|
|
|
db49af |
uint64_t snamestrs;
|
|
|
db49af |
|
|
|
db49af |
int64_t omembers;
|
|
|
db49af |
int64_t osymrefs;
|
|
|
db49af |
int64_t onamestrs;
|
|
|
db49af |
int64_t omemfixup;
|
|
|
db49af |
|
|
|
db49af |
char * base;
|
|
|
db49af |
unsigned char * ubase;
|
|
|
db49af |
|
|
|
db49af |
char * ch;
|
|
|
db49af |
unsigned char * uch;
|
|
|
db49af |
|
|
|
db49af |
char * namebase;
|
|
|
db49af |
char * namestr;
|
|
|
db49af |
char * strtbl;
|
|
|
db49af |
|
|
|
db49af |
uint64_t idx;
|
|
|
db49af |
uint64_t mapidx;
|
|
|
db49af |
uint64_t cmpidx;
|
|
|
db49af |
|
|
|
db49af |
off_t (*armap_write_uint32)(
|
|
|
db49af |
unsigned char *,
|
|
|
db49af |
uint32_t);
|
|
|
db49af |
|
|
|
db49af |
off_t (*armap_write_uint64)(
|
|
|
db49af |
unsigned char *,
|
|
|
db49af |
uint64_t);
|
|
|
db49af |
|
|
|
db49af |
/* init */
|
|
|
db49af |
nmembers = nsymrefs = ssymstrs = mapattr = 0;
|
|
|
db49af |
sarchive = smembers = ssymrefs = snamestrs = 0;
|
|
|
db49af |
omembers = osymrefs = onamestrs = 0;
|
|
|
db49af |
|
|
|
db49af |
if (!arctxv || !arctxv[0])
|
|
|
db49af |
return -1;
|
|
|
db49af |
|
|
|
db49af |
if (!(dctx = slbt_get_archive_ictx(arctxv[0])->dctx))
|
|
|
db49af |
return -1;
|
|
|
db49af |
|
|
|
db49af |
/* determine armap type and size of archive elements */
|
|
|
db49af |
for (armap=0,arnames=0,arctxp=arctxv; *arctxp; arctxp++) {
|
|
|
db49af |
if (slbt_get_archive_ictx(*arctxp)->dctx != dctx)
|
|
|
db49af |
return SLBT_CUSTOM_ERROR(
|
|
|
db49af |
dctx,
|
|
|
db49af |
SLBT_ERR_AR_DRIVER_MISMATCH);
|
|
|
db49af |
|
|
|
db49af |
meta = (*arctxp)->meta;
|
|
|
db49af |
armap32 = meta->a_armap_primary.ar_armap_common_32;
|
|
|
db49af |
armap64 = meta->a_armap_primary.ar_armap_common_64;
|
|
|
db49af |
|
|
|
db49af |
for (memberp=meta->a_memberv; memberp && *memberp; memberp++) {
|
|
|
db49af |
meminfo = *memberp;
|
|
|
db49af |
|
|
|
db49af |
switch (meminfo->ar_member_attr) {
|
|
|
db49af |
case AR_MEMBER_ATTR_ARMAP:
|
|
|
db49af |
if (armap32) {
|
|
|
db49af |
if (mapattr == 0) {
|
|
|
db49af |
armap = meminfo;
|
|
|
db49af |
mapattr = armap32->ar_armap_attr;
|
|
|
db49af |
} else if (mapattr != armap32->ar_armap_attr) {
|
|
|
db49af |
return SLBT_CUSTOM_ERROR(
|
|
|
db49af |
dctx,
|
|
|
db49af |
SLBT_ERR_AR_ARMAP_MISMATCH);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
nsymrefs += armap32->ar_num_of_symbols;
|
|
|
db49af |
ssymstrs += armap32->ar_size_of_strs;
|
|
|
db49af |
|
|
|
db49af |
} else if (armap64) {
|
|
|
db49af |
if (mapattr == 0) {
|
|
|
db49af |
armap = meminfo;
|
|
|
db49af |
mapattr = armap64->ar_armap_attr;
|
|
|
db49af |
} else if (mapattr != armap64->ar_armap_attr) {
|
|
|
db49af |
return SLBT_CUSTOM_ERROR(
|
|
|
db49af |
dctx,
|
|
|
db49af |
SLBT_ERR_AR_ARMAP_MISMATCH);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
nsymrefs += armap64->ar_num_of_symbols;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
break;
|
|
|
db49af |
|
|
|
db49af |
case AR_MEMBER_ATTR_LINKINFO:
|
|
|
db49af |
break;
|
|
|
db49af |
|
|
|
db49af |
case AR_MEMBER_ATTR_NAMESTRS:
|
|
|
db49af |
snamestrs += meminfo->ar_object_size;
|
|
|
db49af |
|
|
|
db49af |
if (!arnames)
|
|
|
db49af |
arnames = meminfo;
|
|
|
db49af |
|
|
|
db49af |
break;
|
|
|
db49af |
|
|
|
db49af |
default:
|
|
|
db49af |
smembers += sizeof(struct ar_raw_file_header);
|
|
|
db49af |
smembers += meminfo->ar_file_header.ar_file_size;
|
|
|
db49af |
smembers += 1;
|
|
|
db49af |
smembers |= 1;
|
|
|
db49af |
smembers ^= 1;
|
|
|
db49af |
nmembers++;
|
|
|
db49af |
|
|
|
db49af |
break;
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
/* armap size */
|
|
|
db49af |
if (sarmap = 0, sarname = 0, (mapattr == 0)) {
|
|
|
db49af |
(void)0;
|
|
|
db49af |
|
|
|
db49af |
} else if (mapattr & AR_ARMAP_ATTR_SYSV) {
|
|
|
db49af |
if (mapattr & (AR_ARMAP_ATTR_LE_32|AR_ARMAP_ATTR_BE_32)) {
|
|
|
db49af |
sarmap += sizeof(uint32_t);
|
|
|
db49af |
sarmap += sizeof(uint32_t) * nsymrefs;
|
|
|
db49af |
} else {
|
|
|
db49af |
sarmap += sizeof(uint64_t);
|
|
|
db49af |
sarmap += sizeof(uint64_t) * nsymrefs;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
} else if (mapattr & AR_ARMAP_ATTR_BSD) {
|
|
|
db49af |
if (mapattr & (AR_ARMAP_ATTR_LE_32|AR_ARMAP_ATTR_BE_32)) {
|
|
|
db49af |
sarmap += 2 * sizeof(uint32_t);
|
|
|
db49af |
sarmap += 2 * sizeof(uint32_t) * nsymrefs;
|
|
|
db49af |
} else {
|
|
|
db49af |
sarmap += 2 * sizeof(uint64_t);
|
|
|
db49af |
sarmap += 2 * sizeof(uint64_t) * nsymrefs;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
sarname += armap->ar_file_header.ar_file_size;
|
|
|
db49af |
sarname -= armap->ar_object_size;
|
|
|
db49af |
} else {
|
|
|
db49af |
return SLBT_CUSTOM_ERROR(dctx,SLBT_ERR_FLOW_ERROR);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
32c230 |
ssymstrs += 1;
|
|
|
32c230 |
ssymstrs |= 1;
|
|
|
32c230 |
ssymstrs ^= 1;
|
|
|
32c230 |
|
|
|
6b3bd5 |
/* (debugging) */
|
|
|
6b3bd5 |
(void)nmembers;
|
|
|
6b3bd5 |
|
|
|
db49af |
/* long-names member alignment */
|
|
|
db49af |
snamestrs += 1;
|
|
|
db49af |
snamestrs |= 1;
|
|
|
db49af |
snamestrs ^= 1;
|
|
|
db49af |
|
|
|
db49af |
/* archive size */
|
|
|
db49af |
sarchive = sizeof(struct ar_raw_signature);
|
|
|
db49af |
sarchive += armap ? sizeof(struct ar_raw_file_header) : 0;
|
|
|
db49af |
sarchive += arnames ? sizeof(struct ar_raw_file_header) : 0;
|
|
|
db49af |
sarchive += sarname;
|
|
|
db49af |
sarchive += sarmap;
|
|
|
db49af |
sarchive += ssymstrs;
|
|
|
db49af |
sarchive += snamestrs;
|
|
|
db49af |
sarchive += smembers;
|
|
|
db49af |
|
|
|
db49af |
/* offset from archive base to first public member */
|
|
|
db49af |
omembers = sarchive;
|
|
|
db49af |
omembers -= smembers;
|
|
|
db49af |
|
|
|
db49af |
|
|
|
db49af |
/* create in-memory archive */
|
|
|
db49af |
if (slbt_create_anonymous_archive_ctx(dctx,sarchive,&arctx) < 0)
|
|
|
db49af |
return SLBT_NESTED_ERROR(dctx);
|
|
|
db49af |
|
|
|
db49af |
|
|
|
db49af |
/* get ready for writing */
|
|
|
db49af |
base = arctx->map->map_addr;
|
|
|
db49af |
ubase = arctx->map->map_addr;
|
|
|
db49af |
|
|
|
db49af |
|
|
|
db49af |
/* archive header */
|
|
|
db49af |
ch = base;
|
|
|
db49af |
memcpy(ch,ar_signature,sizeof(struct ar_raw_signature));
|
|
|
db49af |
ch += sizeof(struct ar_raw_signature);
|
|
|
db49af |
|
|
|
db49af |
|
|
|
db49af |
/* armap header */
|
|
|
db49af |
if (armap) {
|
|
|
db49af |
arhdr = (struct ar_raw_file_header *)ch;
|
|
|
db49af |
memcpy(arhdr,armap->ar_member_data,sizeof(*arhdr)+sarname);
|
|
|
db49af |
|
|
|
db49af |
nwritten = armap->ar_file_header.ar_time_date_stamp
|
|
|
db49af |
? sprintf(arhdr->ar_time_date_stamp,PPRII64,time(0))
|
|
|
db49af |
: 0;
|
|
|
db49af |
|
|
|
db49af |
if (nwritten < 0)
|
|
|
51c276 |
return slbt_ar_merge_archives_fail(
|
|
|
db49af |
arctx,0,0,
|
|
|
db49af |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
db49af |
|
|
|
db49af |
for (nbytes=nwritten; nbytes < sizeof(arhdr->ar_time_date_stamp); nbytes++)
|
|
|
db49af |
arhdr->ar_time_date_stamp[nbytes] = AR_DEC_PADDING;
|
|
|
db49af |
|
|
|
db49af |
nwritten = sprintf(
|
|
|
db49af |
arhdr->ar_file_size,PPRIU64,
|
|
|
db49af |
sarname + sarmap + ssymstrs);
|
|
|
db49af |
|
|
|
db49af |
if (nwritten < 0)
|
|
|
51c276 |
return slbt_ar_merge_archives_fail(
|
|
|
db49af |
arctx,0,0,
|
|
|
db49af |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
db49af |
|
|
|
db49af |
for (nbytes=nwritten; nbytes < sizeof(arhdr->ar_file_size); nbytes++)
|
|
|
db49af |
arhdr->ar_file_size[nbytes] = AR_DEC_PADDING;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
|
|
|
db49af |
/* arnames header (sysv only) */
|
|
|
db49af |
if (arnames) {
|
|
|
db49af |
ch = base;
|
|
|
db49af |
ch += omembers;
|
|
|
db49af |
ch -= snamestrs;
|
|
|
db49af |
ch -= sizeof(struct ar_raw_file_header);
|
|
|
db49af |
|
|
|
db49af |
namebase = ch;
|
|
|
db49af |
namebase += sizeof(struct ar_raw_file_header);
|
|
|
db49af |
|
|
|
db49af |
memset(namebase,0,snamestrs);
|
|
|
db49af |
namestr = namebase;
|
|
|
db49af |
|
|
|
db49af |
arhdr = (struct ar_raw_file_header *)ch;
|
|
|
db49af |
memcpy(arhdr,arnames->ar_member_data,sizeof(*arhdr));
|
|
|
db49af |
|
|
|
db49af |
nwritten = arnames->ar_file_header.ar_time_date_stamp
|
|
|
db49af |
? sprintf(arhdr->ar_time_date_stamp,PPRII64,time(0))
|
|
|
db49af |
: 0;
|
|
|
db49af |
|
|
|
db49af |
if (nwritten < 0)
|
|
|
51c276 |
return slbt_ar_merge_archives_fail(
|
|
|
db49af |
arctx,0,0,
|
|
|
db49af |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
db49af |
|
|
|
db49af |
for (nbytes=nwritten; nbytes < sizeof(arhdr->ar_time_date_stamp); nbytes++)
|
|
|
db49af |
arhdr->ar_time_date_stamp[nbytes] = AR_DEC_PADDING;
|
|
|
db49af |
|
|
|
db49af |
nwritten = sprintf(
|
|
|
db49af |
arhdr->ar_file_size,PPRIU64,
|
|
|
db49af |
snamestrs);
|
|
|
db49af |
|
|
|
db49af |
if (nwritten < 0)
|
|
|
51c276 |
return slbt_ar_merge_archives_fail(
|
|
|
db49af |
arctx,0,0,
|
|
|
db49af |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
db49af |
|
|
|
db49af |
for (nbytes=nwritten; nbytes < sizeof(arhdr->ar_file_size); nbytes++)
|
|
|
db49af |
arhdr->ar_file_size[nbytes] = AR_DEC_PADDING;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
|
|
|
db49af |
/* armap data (preparation) */
|
|
|
db49af |
armap_write_uint32 = 0;
|
|
|
db49af |
armap_write_uint64 = 0;
|
|
|
db49af |
|
|
|
db49af |
bsdmap32 = 0;
|
|
|
db49af |
bsdmap64 = 0;
|
|
|
db49af |
|
|
|
db49af |
if (mapattr & AR_ARMAP_ATTR_BE_32)
|
|
|
db49af |
armap_write_uint32 = slbt_armap_write_be_32;
|
|
|
db49af |
|
|
|
db49af |
else if (mapattr & AR_ARMAP_ATTR_LE_32)
|
|
|
db49af |
armap_write_uint32 = slbt_armap_write_le_32;
|
|
|
db49af |
|
|
|
db49af |
else if (mapattr & AR_ARMAP_ATTR_BE_64)
|
|
|
db49af |
armap_write_uint64 = slbt_armap_write_be_64;
|
|
|
db49af |
|
|
|
db49af |
else if (mapattr & AR_ARMAP_ATTR_LE_64)
|
|
|
db49af |
armap_write_uint64 = slbt_armap_write_le_64;
|
|
|
db49af |
|
|
|
db49af |
uch = ubase;
|
|
|
db49af |
uch += sizeof(struct ar_raw_signature);
|
|
|
db49af |
uch += sizeof(struct ar_raw_file_header);
|
|
|
db49af |
uch += sarname;
|
|
|
db49af |
|
|
|
db49af |
if (mapattr & AR_ARMAP_ATTR_SYSV) {
|
|
|
db49af |
if (armap_write_uint32) {
|
|
|
db49af |
uch += armap_write_uint32(uch,nsymrefs);
|
|
|
db49af |
|
|
|
db49af |
ch = base;
|
|
|
db49af |
ch += uch - ubase;
|
|
|
db49af |
ch += sizeof(uint32_t) * nsymrefs;
|
|
|
db49af |
} else {
|
|
|
db49af |
uch += armap_write_uint64(uch,nsymrefs);
|
|
|
db49af |
|
|
|
db49af |
ch = base;
|
|
|
db49af |
ch += uch - ubase;
|
|
|
db49af |
ch += sizeof(uint64_t) * nsymrefs;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
} else if (mapattr & AR_ARMAP_ATTR_BSD) {
|
|
|
db49af |
strtbl = base;
|
|
|
db49af |
strtbl += omembers;
|
|
|
db49af |
strtbl -= ssymstrs;
|
|
|
db49af |
|
|
|
db49af |
memset(strtbl,0,ssymstrs);
|
|
|
db49af |
|
|
|
db49af |
if (armap_write_uint32) {
|
|
|
db49af |
if (!(bsdmap32 = calloc(2*nsymrefs,sizeof(struct armap_buffer_32))))
|
|
|
51c276 |
return slbt_ar_merge_archives_fail(
|
|
|
db49af |
arctx,0,0,
|
|
|
db49af |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
db49af |
|
|
|
db49af |
bsdsort32 = &bsdmap32[nsymrefs];
|
|
|
db49af |
|
|
|
db49af |
} else {
|
|
|
db49af |
if (!(bsdmap64 = calloc(2*nsymrefs,sizeof(struct armap_buffer_64))))
|
|
|
51c276 |
return slbt_ar_merge_archives_fail(
|
|
|
db49af |
arctx,0,0,
|
|
|
db49af |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
db49af |
|
|
|
db49af |
bsdsort64 = &bsdmap64[nsymrefs];
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
/* main iteration (armap data, long-names, public members) */
|
|
|
db49af |
for (mapidx=0,arctxp=arctxv; *arctxp; arctxp++) {
|
|
|
db49af |
meta = (*arctxp)->meta;
|
|
|
db49af |
armap32 = meta->a_armap_primary.ar_armap_common_32;
|
|
|
db49af |
armap64 = meta->a_armap_primary.ar_armap_common_64;
|
|
|
db49af |
|
|
|
db49af |
if ((memberp = meta->a_memberv)) {
|
|
|
db49af |
for (omemfixup=0; *memberp && !omemfixup; memberp++) {
|
|
|
db49af |
meminfo = *memberp;
|
|
|
db49af |
|
|
|
db49af |
switch (meminfo->ar_member_attr) {
|
|
|
db49af |
case AR_MEMBER_ATTR_ARMAP:
|
|
|
db49af |
case AR_MEMBER_ATTR_LINKINFO:
|
|
|
db49af |
case AR_MEMBER_ATTR_NAMESTRS:
|
|
|
db49af |
break;
|
|
|
db49af |
|
|
|
db49af |
default:
|
|
|
db49af |
omemfixup = (int64_t)meminfo->ar_member_data;
|
|
|
db49af |
omemfixup -= (int64_t)meta->r_archive.map_addr;
|
|
|
db49af |
break;
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
for (memberp=meta->a_memberv; memberp && *memberp; memberp++) {
|
|
|
db49af |
meminfo = *memberp;
|
|
|
db49af |
|
|
|
db49af |
switch (meminfo->ar_member_attr) {
|
|
|
db49af |
case AR_MEMBER_ATTR_ARMAP:
|
|
|
db49af |
if (armap32 && (mapattr & AR_ARMAP_ATTR_SYSV)) {
|
|
|
db49af |
symref32 = armap32->ar_symrefs;
|
|
|
db49af |
|
|
|
db49af |
for (idx=0; idx<armap32->ar_num_of_symbols; idx++) {
|
|
|
db49af |
uch += armap_write_uint32(
|
|
|
db49af |
uch,
|
|
|
db49af |
symref32[idx].ar_member_offset + omembers - omemfixup);
|
|
|
db49af |
|
|
|
db49af |
strcpy(ch,&armap32->ar_string_table[symref32[idx].ar_name_offset]);
|
|
|
db49af |
ch += strlen(ch);
|
|
|
db49af |
ch++;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
} else if (armap64 && (mapattr & AR_ARMAP_ATTR_SYSV)) {
|
|
|
db49af |
symref64 = armap64->ar_symrefs;
|
|
|
db49af |
|
|
|
db49af |
for (idx=0; idx<armap64->ar_num_of_symbols; idx++) {
|
|
|
db49af |
uch += armap_write_uint64(
|
|
|
db49af |
uch,
|
|
|
db49af |
symref64[idx].ar_member_offset + omembers - omemfixup);
|
|
|
db49af |
|
|
|
db49af |
strcpy(ch,&armap64->ar_string_table[symref64[idx].ar_name_offset]);
|
|
|
db49af |
ch += strlen(ch);
|
|
|
db49af |
ch++;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
} else if (armap32 && (mapattr & AR_ARMAP_ATTR_BSD)) {
|
|
|
db49af |
symref32 = armap32->ar_symrefs;
|
|
|
db49af |
|
|
|
db49af |
for (idx=0; idx<armap32->ar_num_of_symbols; idx++) {
|
|
|
db49af |
bsdmap32[mapidx].moffset = symref32[idx].ar_member_offset;
|
|
|
db49af |
bsdmap32[mapidx].moffset += omembers - omemfixup;
|
|
|
db49af |
|
|
|
db49af |
bsdmap32[mapidx].symname = armap32->ar_string_table;
|
|
|
db49af |
bsdmap32[mapidx].symname += symref32[idx].ar_name_offset;
|
|
|
db49af |
|
|
|
db49af |
mapidx++;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
} else if (armap64 && (mapattr & AR_ARMAP_ATTR_BSD)) {
|
|
|
db49af |
symref64 = armap64->ar_symrefs;
|
|
|
db49af |
|
|
|
db49af |
for (idx=0; idx<armap64->ar_num_of_symbols; idx++) {
|
|
|
db49af |
bsdmap64[mapidx].moffset = symref64[idx].ar_member_offset;
|
|
|
db49af |
bsdmap64[mapidx].moffset += omembers - omemfixup;
|
|
|
db49af |
|
|
|
db49af |
bsdmap64[mapidx].symname = armap64->ar_string_table;
|
|
|
db49af |
bsdmap64[mapidx].symname += symref64[idx].ar_name_offset;
|
|
|
db49af |
|
|
|
db49af |
mapidx++;
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
break;
|
|
|
db49af |
|
|
|
db49af |
case AR_MEMBER_ATTR_LINKINFO:
|
|
|
db49af |
break;
|
|
|
db49af |
|
|
|
db49af |
case AR_MEMBER_ATTR_NAMESTRS:
|
|
|
db49af |
break;
|
|
|
db49af |
|
|
|
db49af |
default:
|
|
|
db49af |
arhdr = meminfo->ar_member_data;
|
|
|
db49af |
|
|
|
db49af |
memcpy(
|
|
|
db49af |
&base[omembers],arhdr,
|
|
|
db49af |
sizeof(*arhdr) + meminfo->ar_file_header.ar_file_size);
|
|
|
db49af |
|
|
|
db49af |
if (meminfo->ar_file_header.ar_header_attr & AR_HEADER_ATTR_SYSV) {
|
|
|
db49af |
if (meminfo->ar_file_header.ar_header_attr & AR_HEADER_ATTR_NAME_REF) {
|
|
|
db49af |
nwritten = sprintf(
|
|
|
db49af |
&base[omembers],"/"PPRII64,
|
|
|
db49af |
namestr - namebase);
|
|
|
db49af |
|
|
|
db49af |
if (nwritten < 0)
|
|
|
db49af |
SLBT_SYSTEM_ERROR(dctx,0);
|
|
|
db49af |
|
|
|
db49af |
for (nbytes=nwritten; nbytes < sizeof(arhdr->ar_file_id); nbytes++)
|
|
|
db49af |
base[omembers + nbytes] = AR_DEC_PADDING;
|
|
|
db49af |
|
|
|
db49af |
strcpy(namestr,meminfo->ar_file_header.ar_member_name);
|
|
|
db49af |
namestr += strlen(namestr);
|
|
|
db49af |
*namestr++ = '/';
|
|
|
db49af |
*namestr++ = AR_OBJ_PADDING;
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
omembers += sizeof(*arhdr);
|
|
|
db49af |
omembers += meminfo->ar_file_header.ar_file_size;
|
|
|
db49af |
omembers += 1;
|
|
|
db49af |
omembers |= 1;
|
|
|
db49af |
omembers ^= 1;
|
|
|
db49af |
break;
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
/* bsd variant: also sort the string table (because we can:=)) */
|
|
|
db49af |
if (bsdmap32) {
|
|
|
db49af |
for (mapidx=0; mapidx
|
|
|
db49af |
for (cmpidx=0; cmpidx
|
|
|
db49af |
if (strcmp(bsdmap32[cmpidx].symname,bsdmap32[mapidx].symname) < 0)
|
|
|
db49af |
bsdmap32[mapidx].baseidx++;
|
|
|
db49af |
|
|
|
db49af |
/* a symbol might be present in more than one member; */
|
|
|
db49af |
/* see whether ar_member_offset has already been set) */
|
|
|
db49af |
for (mapidx=0,ch=strtbl; mapidx
|
|
|
db49af |
idx = bsdmap32[mapidx].baseidx;
|
|
|
db49af |
|
|
|
db49af |
for (; bsdsort32[idx].moffset; )
|
|
|
db49af |
idx++;
|
|
|
db49af |
|
|
|
db49af |
bsdsort32[idx].moffset = bsdmap32[mapidx].moffset;
|
|
|
db49af |
bsdsort32[idx].symname = bsdmap32[mapidx].symname;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
uch += armap_write_uint32(uch,2*sizeof(uint32_t)*nsymrefs);
|
|
|
db49af |
|
|
|
db49af |
for (mapidx=0,ch=strtbl; mapidx
|
|
|
db49af |
uch += armap_write_uint32(uch,ch-strtbl);
|
|
|
db49af |
uch += armap_write_uint32(uch,bsdsort32[mapidx].moffset);
|
|
|
db49af |
|
|
|
db49af |
strcpy(ch,bsdsort32[mapidx].symname);
|
|
|
db49af |
ch += strlen(ch);
|
|
|
db49af |
ch++;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
e094ec |
uch += armap_write_uint32(uch,ssymstrs);
|
|
|
db49af |
|
|
|
db49af |
free(bsdmap32);
|
|
|
db49af |
|
|
|
db49af |
} else if (bsdmap64) {
|
|
|
db49af |
for (mapidx=0; mapidx
|
|
|
db49af |
for (cmpidx=0; cmpidx
|
|
|
db49af |
if (strcmp(bsdmap64[cmpidx].symname,bsdmap64[mapidx].symname) < 0)
|
|
|
db49af |
bsdmap64[mapidx].baseidx++;
|
|
|
db49af |
|
|
|
db49af |
/* a symbol might be present in more than one member; */
|
|
|
db49af |
/* see whether ar_member_offset has already been set) */
|
|
|
db49af |
for (mapidx=0,ch=strtbl; mapidx
|
|
|
db49af |
idx = bsdmap64[mapidx].baseidx;
|
|
|
db49af |
|
|
|
db49af |
for (; bsdsort64[idx].moffset; )
|
|
|
db49af |
idx++;
|
|
|
db49af |
|
|
|
db49af |
bsdsort64[idx].moffset = bsdmap64[mapidx].moffset;
|
|
|
db49af |
bsdsort64[idx].symname = bsdmap64[mapidx].symname;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
uch += armap_write_uint64(uch,2*sizeof(uint64_t)*nsymrefs);
|
|
|
db49af |
|
|
|
db49af |
for (mapidx=0,ch=strtbl; mapidx
|
|
|
db49af |
uch += armap_write_uint64(uch,ch-strtbl);
|
|
|
db49af |
uch += armap_write_uint64(uch,bsdsort64[mapidx].moffset);
|
|
|
db49af |
|
|
|
db49af |
strcpy(ch,bsdsort64[mapidx].symname);
|
|
|
db49af |
ch += strlen(ch);
|
|
|
db49af |
ch++;
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
e094ec |
uch += armap_write_uint64(uch,ssymstrs);
|
|
|
db49af |
|
|
|
db49af |
free(bsdmap64);
|
|
|
db49af |
}
|
|
|
db49af |
|
|
|
db49af |
struct slbt_archive_ctx_impl * ictx;
|
|
|
db49af |
ictx = slbt_get_archive_ictx(arctx);
|
|
|
db49af |
|
|
|
51c276 |
if (slbt_ar_get_archive_meta(dctx,arctx->map,&ictx->meta) < 0)
|
|
|
51c276 |
return slbt_ar_merge_archives_fail(
|
|
|
db49af |
arctx,0,0,
|
|
|
db49af |
SLBT_NESTED_ERROR(dctx));
|
|
|
db49af |
|
|
|
db49af |
ictx->actx.meta = ictx->meta;
|
|
|
db49af |
|
|
|
db49af |
*arctxm = arctx;
|
|
|
db49af |
|
|
|
db49af |
return 0;
|
|
|
db49af |
}
|
|
|
e06cc0 |
|
|
|
e06cc0 |
|
|
|
e06cc0 |
int slbt_ar_get_varchive_ctx(
|
|
|
e06cc0 |
const struct slbt_driver_ctx * dctx,
|
|
|
e06cc0 |
struct slbt_archive_ctx ** pctx)
|
|
|
e06cc0 |
{
|
|
|
e06cc0 |
struct slbt_archive_ctx * ctx;
|
|
|
e06cc0 |
struct slbt_archive_ctx_impl * ictx;
|
|
|
e06cc0 |
void * base;
|
|
|
e06cc0 |
size_t size;
|
|
|
e06cc0 |
|
|
|
e06cc0 |
size = sizeof(struct ar_raw_signature);
|
|
|
e06cc0 |
|
|
|
e06cc0 |
if (slbt_create_anonymous_archive_ctx(dctx,size,&ctx) < 0)
|
|
|
e06cc0 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
e06cc0 |
|
|
|
e06cc0 |
ictx = slbt_get_archive_ictx(ctx);
|
|
|
e06cc0 |
|
|
|
e06cc0 |
base = ctx->map->map_addr;
|
|
|
e06cc0 |
memcpy(base,ar_signature,size);
|
|
|
e06cc0 |
|
|
|
e06cc0 |
if (slbt_ar_get_archive_meta(dctx,ctx->map,&ictx->meta) < 0) {
|
|
|
e06cc0 |
slbt_ar_free_archive_ctx(ctx);
|
|
|
e06cc0 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
e06cc0 |
}
|
|
|
e06cc0 |
|
|
|
e06cc0 |
ictx->path = slbt_ar_self_dlunit;
|
|
|
e06cc0 |
ictx->actx.meta = ictx->meta;
|
|
|
e06cc0 |
ictx->actx.path = &ictx->path;
|
|
|
e06cc0 |
|
|
|
e06cc0 |
*pctx = ctx;
|
|
|
e06cc0 |
|
|
|
e06cc0 |
return 0;
|
|
|
e06cc0 |
}
|