|
|
d42469 |
/*******************************************************************/
|
|
|
d42469 |
/* slibtool: a skinny libtool implementation, written in C */
|
|
|
d42469 |
/* Copyright (C) 2016--2024 SysDeer Technologies, LLC */
|
|
|
d42469 |
/* Released under the Standard MIT License; see COPYING.SLIBTOOL. */
|
|
|
d42469 |
/*******************************************************************/
|
|
|
d42469 |
|
|
|
d42469 |
#include <ctype.h>
|
|
|
d42469 |
#include <stdint.h>
|
|
|
d42469 |
#include <stddef.h>
|
|
|
d42469 |
#include <stdlib.h>
|
|
|
d42469 |
#include <string.h>
|
|
|
d42469 |
#include <sys/mman.h>
|
|
|
d42469 |
|
|
|
d42469 |
#include <slibtool/slibtool.h>
|
|
|
d42469 |
#include "slibtool_driver_impl.h"
|
|
|
d42469 |
#include "slibtool_errinfo_impl.h"
|
|
|
d42469 |
|
|
|
d42469 |
static int slbt_lib_free_symlist_ctx_impl(
|
|
|
d42469 |
struct slbt_symlist_ctx_impl * ctx,
|
|
|
d42469 |
struct slbt_input * mapinfo,
|
|
|
d42469 |
int ret)
|
|
|
d42469 |
{
|
|
|
d42469 |
if (mapinfo)
|
|
|
d42469 |
slbt_fs_unmap_input(mapinfo);
|
|
|
d42469 |
|
|
|
d42469 |
if (ctx) {
|
|
|
d42469 |
if (ctx->pathbuf)
|
|
|
d42469 |
free(ctx->pathbuf);
|
|
|
d42469 |
|
|
|
d42469 |
if (ctx->symstrs)
|
|
|
d42469 |
free(ctx->symstrs);
|
|
|
d42469 |
|
|
|
d42469 |
if (ctx->symstrv)
|
|
|
d42469 |
free(ctx->symstrv);
|
|
|
d42469 |
|
|
|
d42469 |
free(ctx);
|
|
|
d42469 |
}
|
|
|
d42469 |
|
|
|
d42469 |
return ret;
|
|
|
d42469 |
}
|
|
|
d42469 |
|
|
|
d42469 |
int slbt_lib_get_symlist_ctx(
|
|
|
d42469 |
const struct slbt_driver_ctx * dctx,
|
|
|
d42469 |
const char * path,
|
|
|
d42469 |
struct slbt_symlist_ctx ** pctx)
|
|
|
d42469 |
{
|
|
|
d42469 |
struct slbt_symlist_ctx_impl * ctx;
|
|
|
d42469 |
struct slbt_input mapinfo;
|
|
|
d42469 |
size_t nsyms;
|
|
|
d42469 |
char * ch;
|
|
|
d42469 |
char * cap;
|
|
|
d42469 |
char * src;
|
|
|
d42469 |
const char ** psym;
|
|
|
d42469 |
char dummy;
|
|
|
bb9df1 |
int cint;
|
|
|
d42469 |
bool fvalid;
|
|
|
d42469 |
|
|
|
d42469 |
/* map symlist file temporarily */
|
|
|
d42469 |
if (slbt_fs_map_input(dctx,-1,path,PROT_READ,&mapinfo) < 0)
|
|
|
d42469 |
return SLBT_NESTED_ERROR(dctx);
|
|
|
d42469 |
|
|
|
d42469 |
/* alloc context */
|
|
|
d42469 |
if (!(ctx = calloc(1,sizeof(*ctx))))
|
|
|
d42469 |
return slbt_lib_free_symlist_ctx_impl(
|
|
|
d42469 |
ctx,&mapinfo,
|
|
|
d42469 |
SLBT_BUFFER_ERROR(dctx));
|
|
|
d42469 |
|
|
|
d42469 |
/* count symbols */
|
|
|
d42469 |
src = mapinfo.size ? mapinfo.addr : &dummy;
|
|
|
d42469 |
cap = &src[mapinfo.size];
|
|
|
d42469 |
|
|
|
bb9df1 |
for (; (src
|
|
|
d42469 |
src++;
|
|
|
d42469 |
|
|
|
d42469 |
for (ch=src,nsyms=0; ch
|
|
|
bb9df1 |
for (; (ch
|
|
|
d42469 |
ch++;
|
|
|
d42469 |
|
|
|
d42469 |
fvalid = false;
|
|
|
d42469 |
|
|
|
bb9df1 |
for (; (ch
|
|
|
d42469 |
fvalid = (*ch++ == '\n') || fvalid;
|
|
|
d42469 |
|
|
|
d42469 |
if (!fvalid)
|
|
|
d42469 |
return slbt_lib_free_symlist_ctx_impl(
|
|
|
d42469 |
ctx,&mapinfo,
|
|
|
d42469 |
SLBT_CUSTOM_ERROR(
|
|
|
d42469 |
dctx,
|
|
|
d42469 |
SLBT_ERR_FLOW_ERROR));
|
|
|
d42469 |
}
|
|
|
d42469 |
|
|
|
d42469 |
/* clone path, alloc string buffer and symbol vector */
|
|
|
d42469 |
if (!(ctx->pathbuf = strdup(path)))
|
|
|
d42469 |
return slbt_lib_free_symlist_ctx_impl(
|
|
|
d42469 |
ctx,&mapinfo,
|
|
|
d42469 |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
d42469 |
|
|
|
d42469 |
if (!(ctx->symstrs = calloc(mapinfo.size+1,1)))
|
|
|
d42469 |
return slbt_lib_free_symlist_ctx_impl(
|
|
|
d42469 |
ctx,&mapinfo,
|
|
|
d42469 |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
d42469 |
|
|
|
d42469 |
if (!(ctx->symstrv = calloc(nsyms+1,sizeof(char *))))
|
|
|
d42469 |
return slbt_lib_free_symlist_ctx_impl(
|
|
|
d42469 |
ctx,&mapinfo,
|
|
|
d42469 |
SLBT_SYSTEM_ERROR(dctx,0));
|
|
|
d42469 |
|
|
|
d42469 |
/* copy the source to the allocated string buffer */
|
|
|
d42469 |
memcpy(ctx->symstrs,mapinfo.addr,mapinfo.size);
|
|
|
d42469 |
slbt_fs_unmap_input(&mapinfo);
|
|
|
d42469 |
|
|
|
d42469 |
/* populate the symbol vector, handle whitespace */
|
|
|
d42469 |
src = ctx->symstrs;
|
|
|
d42469 |
cap = &src[mapinfo.size];
|
|
|
d42469 |
|
|
|
bb9df1 |
for (; (src
|
|
|
d42469 |
src++;
|
|
|
d42469 |
|
|
|
d42469 |
for (ch=src,psym=ctx->symstrv; ch
|
|
|
d42469 |
*psym = ch;
|
|
|
d42469 |
|
|
|
bb9df1 |
for (; (ch
|
|
|
d42469 |
ch++;
|
|
|
d42469 |
|
|
|
bb9df1 |
for (; (ch
|
|
|
d42469 |
*ch++ = '\0';
|
|
|
d42469 |
}
|
|
|
d42469 |
|
|
|
d42469 |
/* all done */
|
|
|
d42469 |
ctx->dctx = dctx;
|
|
|
d42469 |
ctx->path = ctx->pathbuf;
|
|
|
d42469 |
ctx->sctx.path = &ctx->path;
|
|
|
d42469 |
ctx->sctx.symstrv = ctx->symstrv;
|
|
|
d42469 |
|
|
|
d42469 |
*pctx = &ctx->sctx;
|
|
|
d42469 |
|
|
|
d42469 |
return 0;
|
|
|
d42469 |
}
|
|
|
d42469 |
|
|
|
d42469 |
void slbt_lib_free_symlist_ctx(struct slbt_symlist_ctx * ctx)
|
|
|
d42469 |
{
|
|
|
d42469 |
struct slbt_symlist_ctx_impl * ictx;
|
|
|
d42469 |
uintptr_t addr;
|
|
|
d42469 |
|
|
|
d42469 |
if (ctx) {
|
|
|
d42469 |
addr = (uintptr_t)ctx - offsetof(struct slbt_symlist_ctx_impl,sctx);
|
|
|
d42469 |
ictx = (struct slbt_symlist_ctx_impl *)addr;
|
|
|
d42469 |
slbt_lib_free_symlist_ctx_impl(ictx,0,0);
|
|
|
d42469 |
}
|
|
|
d42469 |
}
|