summaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2025-05-31 21:34:17 +0000
committermidipix <writeonce@midipix.org>2025-05-31 22:11:05 +0000
commitd9d2d9175f0e52d873e5bf9210a1f35fd3a49b7c (patch)
tree94f05e51309973c64f5428ceebfd817c69f51447 /src
parent1c0129c0e4039a3b337cc54a2b9cbace7e6a0849 (diff)
downloadperk-d9d2d9175f0e52d873e5bf9210a1f35fd3a49b7c.tar.bz2
perk-d9d2d9175f0e52d873e5bf9210a1f35fd3a49b7c.tar.xz
driver: pe_lib_get_unit_ctx(): added handling of archives and archive members.
Diffstat (limited to 'src')
-rw-r--r--src/driver/pe_amain.c5
-rw-r--r--src/driver/pe_unit_ctx.c122
-rw-r--r--src/internal/perk_driver_impl.h3
-rw-r--r--src/output/pe_output_error.c6
4 files changed, 133 insertions, 3 deletions
diff --git a/src/driver/pe_amain.c b/src/driver/pe_amain.c
index 173f391..606184d 100644
--- a/src/driver/pe_amain.c
+++ b/src/driver/pe_amain.c
@@ -13,7 +13,10 @@
#ifndef PERK_DRIVER_FLAGS
#define PERK_DRIVER_FLAGS PERK_DRIVER_VERBOSITY_ERRORS \
- | PERK_DRIVER_VERBOSITY_UTILITY
+ | PERK_DRIVER_VERBOSITY_UTILITY \
+ | PERK_DRIVER_AR_STRICT_PE \
+ | PERK_DRIVER_AR_STRICT_PE_ARCH \
+ | PERK_DRIVER_AR_OBJECT_VECTOR
#endif
static const char vermsg[] = "%s%s%s (git://midipix.org/perk): "
diff --git a/src/driver/pe_unit_ctx.c b/src/driver/pe_unit_ctx.c
index 76823b0..0e0373a 100644
--- a/src/driver/pe_unit_ctx.c
+++ b/src/driver/pe_unit_ctx.c
@@ -11,20 +11,118 @@
#include <sys/mman.h>
#include <perk/perk.h>
+#include <perk/perk_arbits.h>
+#include "perk_ar_impl.h"
#include "perk_driver_impl.h"
#include "perk_errinfo_impl.h"
static int pe_lib_free_unit_ctx_impl(struct pe_unit_ctx_impl * ctx, int ret)
{
+ struct pe_image_meta ** pmeta;
if (ctx) {
+ for (pmeta=ctx->objmeta; pmeta && *pmeta; pmeta++)
+ pe_meta_free_image_meta(*pmeta);
+
+ pe_ar_free_archive_meta(ctx->armeta);
pe_meta_free_image_meta(ctx->meta);
pe_raw_unmap_raw_image(&ctx->map);
+ free(ctx->objmeta);
free(ctx);
}
return ret;
}
+static int pe_lib_create_object_vector_or_verify_archive(
+ const struct pe_driver_ctx * dctx,
+ struct pe_unit_ctx_impl * ctx)
+{
+ struct pe_archive_meta * actx;
+ struct pe_archive_meta_impl * ictx;
+ struct pe_driver_ctx_impl * idctx;
+ bool fvector;
+ bool fstrict;
+ bool fpurearch;
+ struct pe_image_meta * meta;
+ struct pe_image_meta ** objmeta;
+ size_t veclen;
+ struct pe_raw_image map;
+ struct ar_meta_member_info ** pmember;
+ struct pe_error_info ** errinfp;
+ enum pe_abi m_abi;
+ enum pe_subtype m_subtype;
+
+ fvector = (dctx->cctx->drvflags & PERK_DRIVER_AR_OBJECT_VECTOR);
+ fstrict = (dctx->cctx->drvflags & PERK_DRIVER_AR_STRICT_PE);
+ fpurearch = (dctx->cctx->drvflags & PERK_DRIVER_AR_STRICT_PE_ARCH);
+
+ if (!fvector && !fstrict && !fpurearch)
+ return 0;
+
+ actx = ctx->armeta;
+ ictx = pe_archive_meta_ictx(actx);
+ idctx = pe_get_driver_ictx(dctx);
+ veclen = ictx->nentries + 1;
+
+ if (fvector && !(ctx->objmeta = calloc(veclen,sizeof(meta))))
+ return PERK_BUFFER_ERROR(dctx);
+
+ if (!actx->a_memberv)
+ return 0;
+
+ for (pmember=actx->a_memberv,objmeta=ctx->objmeta; *pmember; pmember++) {
+ errinfp = idctx->errinfp;
+
+ switch (pmember[0]->ar_member_attr) {
+ case AR_MEMBER_ATTR_ARCHIVE:
+ return PERK_CUSTOM_ERROR(dctx,
+ PERK_ERR_AR_NESTED_ARCHIVE);
+
+ case AR_MEMBER_ATTR_ARMAP:
+ case AR_MEMBER_ATTR_NAMESTRS:
+ case AR_MEMBER_ATTR_LINKINFO:
+ break;
+
+ default:
+ map.map_addr = pmember[0]->ar_object_data;
+ map.map_size = pmember[0]->ar_object_size;
+
+ if (!pe_meta_get_image_meta(dctx,&map,&meta)) {
+ if (fpurearch && (objmeta == ctx->objmeta)) {
+ m_abi = meta->m_abi;
+ m_subtype = meta->m_subtype;
+
+ } else if (fpurearch) {
+ if ((meta->m_abi != m_abi) || (meta->m_subtype != m_subtype))
+ return PERK_CUSTOM_ERROR(dctx,
+ PERK_ERR_AR_MIXED_PE_MEMBERS);
+ }
+
+ if (fvector) {
+ *objmeta++ = meta;
+ } else {
+ pe_meta_free_image_meta(meta);
+ };
+
+
+ } else if (fstrict || fpurearch) {
+ return PERK_CUSTOM_ERROR(dctx,
+ PERK_ERR_AR_NON_PE_MEMBERS);
+
+ } else {
+ idctx->errinfp = errinfp;
+
+ for (; *errinfp; )
+ *errinfp++ = 0;
+ }
+
+ break;
+ }
+ }
+
+ return 0;
+}
+
int pe_lib_get_unit_ctx(
const struct pe_driver_ctx * dctx,
const char * path,
@@ -32,6 +130,8 @@ int pe_lib_get_unit_ctx(
{
struct pe_unit_ctx_impl * ctx;
int prot;
+ char * mark;
+ size_t siglen;
if (!dctx)
return PERK_CUSTOM_ERROR(
@@ -51,13 +151,33 @@ int pe_lib_get_unit_ctx(
return pe_lib_free_unit_ctx_impl(ctx,
PERK_NESTED_ERROR(dctx));
- if (pe_meta_get_image_meta(dctx,&ctx->map,&ctx->meta))
+ if (ctx->map.map_size < (siglen = sizeof(struct ar_raw_signature)))
+ return pe_lib_free_unit_ctx_impl(ctx,
+ PERK_CUSTOM_ERROR(
+ dctx,
+ PERK_ERR_INVALID_IMAGE));
+
+ if (!strncmp((mark = ctx->map.map_addr),AR_SIGNATURE,siglen)) {
+ ctx->armap.map_addr = ctx->map.map_addr;
+ ctx->armap.map_size = ctx->map.map_size;
+
+ if (pe_ar_get_archive_meta(dctx,&ctx->armap,&ctx->armeta))
+ return pe_lib_free_unit_ctx_impl(ctx,
+ PERK_NESTED_ERROR(dctx));
+
+ if (pe_lib_create_object_vector_or_verify_archive(dctx,ctx) < 0)
+ return pe_lib_free_unit_ctx_impl(ctx,
+ PERK_NESTED_ERROR(dctx));
+
+ } else if (pe_meta_get_image_meta(dctx,&ctx->map,&ctx->meta)) {
return pe_lib_free_unit_ctx_impl(ctx,
PERK_NESTED_ERROR(dctx));
+ }
ctx->path = path;
ctx->uctx.path = &ctx->path;
ctx->uctx.meta = ctx->meta;
+ ctx->uctx.armeta= ctx->armeta;
*pctx = &ctx->uctx;
return 0;
diff --git a/src/internal/perk_driver_impl.h b/src/internal/perk_driver_impl.h
index e50d08a..0f992d1 100644
--- a/src/internal/perk_driver_impl.h
+++ b/src/internal/perk_driver_impl.h
@@ -48,6 +48,9 @@ struct pe_unit_ctx_impl {
const char * path;
struct pe_raw_image map;
struct pe_image_meta * meta;
+ struct pe_raw_archive armap;
+ struct pe_archive_meta *armeta;
+ struct pe_image_meta ** objmeta;
struct pe_unit_ctx uctx;
};
diff --git a/src/output/pe_output_error.c b/src/output/pe_output_error.c
index 84a867b..1d818d1 100644
--- a/src/output/pe_output_error.c
+++ b/src/output/pe_output_error.c
@@ -27,13 +27,17 @@ static const char * const pe_error_strings[PERK_ERR_CAP] = {
[PERK_ERR_NULL_CONTEXT] = "null driver or unit context",
[PERK_ERR_NULL_IMAGE] = "null image base pointer",
[PERK_ERR_INVALID_CONTEXT] = "invalid driver or unit context",
- [PERK_ERR_INVALID_IMAGE] = "invalid PE image",
+ [PERK_ERR_INVALID_IMAGE] = "invalid PE image, object, or common archive",
[PERK_ERR_IMAGE_SIZE_ZERO] = "PE image size cannot be zero",
[PERK_ERR_IMAGE_MALFORMED] = "malformed PE image detected",
[PERK_ERR_BAD_DOS_HEADER] = "bad DOS header",
[PERK_ERR_BAD_COFF_HEADER] = "bad COFF header",
[PERK_ERR_BAD_IMAGE_TYPE] = "bad PE image type",
[PERK_ERR_UNSUPPORTED_ABI] = "unsupported image abi",
+
+ [PERK_ERR_AR_NON_PE_MEMBERS] = "format of current archive member is not PE/COFF",
+ [PERK_ERR_AR_MIXED_PE_MEMBERS] = "archive mixes objects of different architectures",
+ [PERK_ERR_AR_NESTED_ARCHIVE] = "nested archives are currently not supported",
};
static const char * pe_output_error_header(const struct pe_error_info * erri)