From 906422a560cdbf078793143a30274a5faed37d6b Mon Sep 17 00:00:00 2001 From: midipix Date: Fri, 30 May 2025 08:51:56 +0000 Subject: arbits: added pe_ar_get_archive_meta(), the framework's archive parser. --- src/arbits/pe_archive_meta.c | 888 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 888 insertions(+) create mode 100644 src/arbits/pe_archive_meta.c (limited to 'src/arbits/pe_archive_meta.c') diff --git a/src/arbits/pe_archive_meta.c b/src/arbits/pe_archive_meta.c new file mode 100644 index 0000000..f5fcf0d --- /dev/null +++ b/src/arbits/pe_archive_meta.c @@ -0,0 +1,888 @@ +/***************************************************************/ +/* perk: PE Resource Kit */ +/* Copyright (C) 2015--2025 SysDeer Technologies, LLC */ +/* Released under GPLv2 and GPLv3; see COPYING.PERK. */ +/***************************************************************/ + +#include +#include +#include +#include +#include + +#include +#include +#include "perk_ar_impl.h" +#include "perk_driver_impl.h" +#include "perk_errinfo_impl.h" +#include "perk_visibility_impl.h" + +/* transient header info vector */ +struct ar_header_info { + struct ar_raw_file_header * phdr; + uint32_t attr; +}; + +static const char ar_signature[] = AR_SIGNATURE; + +static int pe_ar_free_archive_meta_impl(struct pe_archive_meta_impl * meta, int ret) +{ + if (meta) { + if (meta->armaps.armap_symrefs_32) + free(meta->armaps.armap_symrefs_32); + + if (meta->armaps.armap_symrefs_64) + free(meta->armaps.armap_symrefs_64); + + if (meta->hdrinfov) + free(meta->hdrinfov); + + if (meta->namestrs) + free(meta->namestrs); + + if (meta->syminfo) + free(meta->syminfo); + + if (meta->syminfv) + free(meta->syminfv); + + if (meta->memberv) + free(meta->memberv); + + if (meta->offsetv) + free(meta->offsetv); + + if (meta->members) + free(meta->members); + + if (meta->symstrv) + free(meta->symstrv); + + if (meta->mapstrv) + free(meta->mapstrv); + + if (meta->nminfo) + (void)0; + + free(meta); + } + + return ret; +} + + +static int pe_ar_read_octal(const char * mark, int len, uint32_t * dec) +{ + int i; + uint64_t res; + + for (; len && (mark[len-1]==AR_DEC_PADDING); ) + len--; + + for (i=0,res=0; i= '0') && (mark[i] <= '7')) { + res *= 8; + res += (mark[i] - '0'); + } else { + return -1; + } + } + + *dec = res; + + return 0; +} + +static int pe_ar_read_decimal_64(const char * mark, int len, uint64_t * dec) +{ + int i; + uint64_t res; + + for (; len && (mark[len-1]==AR_DEC_PADDING); ) + len--; + + for (i=0,res=0; i= '0') && (mark[i] <= '9')) { + res *= 10; + res += (mark[i] - '0'); + } else { + return -1; + } + } + + *dec = res; + + return 0; +} + +static int pe_ar_read_decimal_32(const char * mark, int len, uint32_t * dec) +{ + uint64_t res; + + if (pe_ar_read_decimal_64(mark,len,&res) < 0) + return -1; + + *dec = res; + + return 0; +} + +static uint32_t pe_ar_get_member_attr(struct ar_meta_member_info * m) +{ + const char * hdrname; + uint32_t hdrattr; + const char * data; + const char * data_cap; + const unsigned char * udata; + unsigned char uch; + const size_t siglen = sizeof(struct ar_raw_signature); + + hdrname = m->ar_file_header.ar_member_name; + hdrattr = m->ar_file_header.ar_header_attr; + + data = m->ar_object_data; + data_cap = &data[m->ar_file_header.ar_file_size]; + + if (hdrattr & AR_HEADER_ATTR_SYSV) { + /* long names member? */ + if ((hdrname[0] == '/') && (hdrname[1] == '/')) + return AR_MEMBER_ATTR_NAMESTRS; + + /* mips 64-bit armap member? */ + else if (!strncmp(hdrname,"/SYM64/",7)) + return AR_MEMBER_ATTR_ARMAP; + + /* armap member? */ + else if (hdrname[0] == '/' && (hdrname[1] == '\0')) + return AR_MEMBER_ATTR_ARMAP; + + /* nested archive? */ + else if (m->ar_file_header.ar_file_size >= siglen) + if (!strncmp(data,ar_signature,siglen)) + return AR_MEMBER_ATTR_ARCHIVE; + + } else if (hdrattr & AR_HEADER_ATTR_BSD) { + if (!strcmp(hdrname,"__.SYMDEF")) + return AR_MEMBER_ATTR_ARMAP; + + else if (!strcmp(hdrname,"__.SYMDEF SORTED")) + return AR_MEMBER_ATTR_ARMAP; + + else if (!strcmp(hdrname,"__.SYMDEF_64")) + return AR_MEMBER_ATTR_ARMAP; + + else if (!strcmp(hdrname,"__.SYMDEF_64 SORTED")) + return AR_MEMBER_ATTR_ARMAP; + } + + /* ascii only data? */ + for (; data= 0x80) + break; + + data++; + } + + if (data == data_cap) + return AR_MEMBER_ATTR_ASCII; + + data = m->ar_object_data; + udata = (unsigned char *)data; + + /* elf object? [quick and dirty] */ + if (m->ar_file_header.ar_file_size >= 5) + if ((udata[0] == 0x7f) + && (udata[1] == 'E') + && (udata[2] == 'L') + && (udata[3] == 'F')) + if ((m->ar_object_attr = AR_OBJECT_ATTR_ELF)) + return AR_MEMBER_ATTR_OBJECT; + + /* coff i386 object? [quick and dirty] */ + if (m->ar_file_header.ar_file_size >= 2) + if ((udata[0] == 0x4c) && (udata[1] == 0x01)) + if ((m->ar_object_attr = AR_OBJECT_ATTR_COFF)) + return AR_MEMBER_ATTR_OBJECT; + + /* coff x86_64 object? [quick and dirty] */ + if (m->ar_file_header.ar_file_size >= 2) + if ((udata[0] == 0x64) && (udata[1] == 0x86)) + if ((m->ar_object_attr = AR_OBJECT_ATTR_COFF)) + return AR_MEMBER_ATTR_OBJECT; + + /* big endian 32-bit macho object? [quick and dirty] */ + if (m->ar_file_header.ar_file_size >= 4) + if ((udata[0] == 0xfe) && (udata[1] == 0xed)) + if ((udata[2] == 0xfa) && (udata[3] == 0xce)) + if ((m->ar_object_attr = AR_OBJECT_ATTR_MACHO)) + return AR_MEMBER_ATTR_OBJECT; + + /* big endian 64-bit macho object? [quick and dirty] */ + if (m->ar_file_header.ar_file_size >= 4) + if ((udata[0] == 0xfe) && (udata[1] == 0xed)) + if ((udata[2] == 0xfa) && (udata[3] == 0xcf)) + if ((m->ar_object_attr = AR_OBJECT_ATTR_MACHO)) + return AR_MEMBER_ATTR_OBJECT; + + /* little endian 32-bit macho object? [quick and dirty] */ + if (m->ar_file_header.ar_file_size >= 4) + if ((udata[3] == 0xfe) && (udata[2] == 0xed)) + if ((udata[1] == 0xfa) && (udata[0] == 0xce)) + if ((m->ar_object_attr = AR_OBJECT_ATTR_MACHO)) + return AR_MEMBER_ATTR_OBJECT; + + /* little endian 64-bit macho object? [quick and dirty] */ + if (m->ar_file_header.ar_file_size >= 4) + if ((udata[3] == 0xfe) && (udata[2] == 0xed)) + if ((udata[1] == 0xfa) && (udata[0] == 0xcf)) + if ((m->ar_object_attr = AR_OBJECT_ATTR_MACHO)) + return AR_MEMBER_ATTR_OBJECT; + + /* all other */ + return AR_MEMBER_ATTR_DEFAULT; +} + +static int pe_ar_parse_primary_armap( + const struct pe_driver_ctx * dctx, + struct pe_archive_meta_impl * m) + +{ + struct ar_meta_member_info * memberp; + const char * hdrname; + uint32_t hdrattr; + + memberp = m->memberv[0]; + hdrname = memberp->ar_file_header.ar_member_name; + hdrattr = memberp->ar_file_header.ar_header_attr; + + if (!(memberp->ar_member_attr & AR_MEMBER_ATTR_ARMAP)) + return 0; + + if (hdrattr & AR_HEADER_ATTR_SYSV) { + /* mips 64-bit armap member? */ + if (!strncmp(hdrname,"/SYM64/",7)) + return pe_ar_parse_primary_armap_sysv_64( + dctx,m); + + /* sysv 32-bit armap member */ + return pe_ar_parse_primary_armap_sysv_32( + dctx,m); + + } else if (hdrattr & AR_HEADER_ATTR_BSD) { + if (!strcmp(hdrname,"__.SYMDEF")) + return pe_ar_parse_primary_armap_bsd_32( + dctx,m); + + else if (!strcmp(hdrname,"__.SYMDEF SORTED")) + return pe_ar_parse_primary_armap_bsd_32( + dctx,m); + + else if (!strcmp(hdrname,"__.SYMDEF_64")) + return pe_ar_parse_primary_armap_bsd_64( + dctx,m); + + else if (!strcmp(hdrname,"__.SYMDEF_64 SORTED")) + return pe_ar_parse_primary_armap_bsd_64( + dctx,m); + } + + return PERK_CUSTOM_ERROR(dctx,PERK_ERR_FLOW_ERROR); +} + +perk_hidden struct ar_meta_member_info * pe_archive_member_from_offset( + struct pe_archive_meta_impl * meta, + off_t offset) +{ + intptr_t l,r,m; + off_t * offsetv; + + l = 0; + r = meta->nentries - 1; + + offsetv = meta->offsetv; + + while (l != r) { + m = (l + r) / 2; + m += (l + r) % 2; + + if (offsetv[m] > offset) { + r = --m; + } else { + l = m; + } + } + + return (offsetv[l] == offset) ? meta->memberv[l] : 0; +} + +int pe_ar_get_archive_meta( + const struct pe_driver_ctx * dctx, + const struct pe_raw_archive * archive, + struct pe_archive_meta ** meta) +{ + const char * mark; + const char * cap; + struct pe_archive_meta_impl * m; + const char * slash; + const char * ch; + const char * fldcap; + size_t nelements; + uint64_t nentries; + uint64_t nmembers; + uint64_t stblsize; + uint64_t filesize; + uint64_t namelen; + uint64_t nameoff; + uint32_t attr; + void * s_addr; + void * m_addr; + const char * s_ptr; + const char * m_ptr; + struct ar_raw_file_header * arhdr; + struct ar_raw_file_header * arlongnames; + struct ar_meta_member_info * memberp; + char * longnamep; + size_t idx; + struct ar_meta_armap_ref_32 * symrefs_32; + struct ar_meta_armap_ref_64 * symrefs_64; + struct ar_header_info * hdrinfov; + struct ar_header_info * hdrinfov_cap; + struct ar_header_info * hdrinfov_next; + struct ar_header_info hdrinfobuf[AR_STACK_VECTOR_ELEMENTS]; + + /* init */ + hdrinfov = hdrinfobuf; + hdrinfov_cap = &hdrinfobuf[AR_STACK_VECTOR_ELEMENTS]; + nelements = AR_STACK_VECTOR_ELEMENTS; + + memset(hdrinfobuf,0,sizeof(hdrinfobuf)); + + mark = archive->map_addr; + cap = &mark[archive->map_size]; + + /* preliminary validation */ + if (archive->map_size < sizeof(struct ar_raw_signature)) + return PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_SIGNATURE); + + else if (strncmp(mark,ar_signature,sizeof(struct ar_raw_signature))) + return PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_SIGNATURE); + + /* alloc */ + if (!(m = calloc(1,sizeof(*m)))) + return PERK_SYSTEM_ERROR(dctx); + + /* associated driver context */ + m->dctx = dctx; + + /* archive map info */ + m->armeta.r_archive.map_addr = archive->map_addr; + m->armeta.r_archive.map_size = archive->map_size; + + /* archive signature */ + m->armeta.r_signature = (struct ar_raw_signature *)mark; + m->armeta.m_signature = (struct ar_meta_signature *)ar_signature; + + /* signature only? */ + if (archive->map_size == sizeof(struct ar_raw_signature)) { + *meta = &m->armeta; + return 0; + } + + mark += sizeof(struct ar_raw_signature); + + /* only trailing null characters past the signature? */ + if (cap < &mark[sizeof(*arhdr)]) + for (ch=mark; char_file_size, + sizeof(arhdr->ar_file_size), + &filesize)) < 0) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_HEADER)); + + mark += sizeof(struct ar_raw_file_header); + + /* stblsize, member name type */ + fldcap = &arhdr->ar_file_id[sizeof(arhdr->ar_file_id)]; + + /* sysv long names table? */ + if ((arhdr->ar_file_id[0] == '/') && (arhdr->ar_file_id[1] == '/')) { + for (ch=&arhdr->ar_file_id[2]; char_file_size, + sizeof(arhdr->ar_file_size), + &namelen) < 0) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_HEADER)); + + + /* duplicate long names member? */ + if (arlongnames) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_DUPLICATE_LONG_NAMES)); + + attr = AR_HEADER_ATTR_FILE_ID | AR_HEADER_ATTR_SYSV; + + stblsize++; + stblsize++; + stblsize++; + + stblsize += namelen; + + arlongnames = arhdr; + + /* the /SYM64/ string must be special cased, also below when it gets copied */ + } else if (!strncmp(arhdr->ar_file_id,"/SYM64/",7)) { + for (ch=&arhdr->ar_file_id[7]; char_file_id[0] == '/') { + if (pe_ar_read_decimal_64( + &arhdr->ar_file_id[1], + sizeof(arhdr->ar_file_id)-1, + &nameoff) < 0) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_HEADER)); + + if (arhdr->ar_file_id[1] == AR_DEC_PADDING) { + attr = AR_HEADER_ATTR_FILE_ID | AR_HEADER_ATTR_SYSV; + stblsize++; + stblsize++; + } else { + attr = AR_HEADER_ATTR_NAME_REF | AR_HEADER_ATTR_SYSV; + } + + /* bsd long name reference? */ + } else if ((arhdr->ar_file_id[0] == '#') + && (arhdr->ar_file_id[1] == '1') + && (arhdr->ar_file_id[2] == '/')) { + if (pe_ar_read_decimal_64( + &arhdr->ar_file_id[3], + sizeof(arhdr->ar_file_id)-3, + &namelen) < 0) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_HEADER)); + + attr = AR_HEADER_ATTR_NAME_REF | AR_HEADER_ATTR_BSD; + + stblsize += namelen + 1; + + /* must be either a sysv short member name, or a (legacy) bsd short name */ + } else { + for (ch=arhdr->ar_file_id,slash=0; (char_file_id) + 1; + } else { + attr = AR_HEADER_ATTR_FILE_ID | AR_HEADER_ATTR_BSD; + stblsize += sizeof(arhdr->ar_file_id) + 1; + } + + for (; chhdrinfov = hdrinfov; + } + + hdrinfov[nentries].phdr = arhdr; + hdrinfov[nentries].attr = attr; + } + + /* allocate name strings, member vector */ + if (!(m->namestrs = calloc(1,stblsize))) + return pe_ar_free_archive_meta_impl( + m,PERK_SYSTEM_ERROR(dctx)); + + if (!(m->offsetv = calloc(nentries+1,sizeof(*m->offsetv)))) + return pe_ar_free_archive_meta_impl( + m,PERK_SYSTEM_ERROR(dctx)); + + if (!(m->memberv = calloc(nentries+1,sizeof(*m->memberv)))) + return pe_ar_free_archive_meta_impl( + m,PERK_SYSTEM_ERROR(dctx)); + + if (!(m->members = calloc(nentries,sizeof(*m->members)))) + return pe_ar_free_archive_meta_impl( + m,PERK_SYSTEM_ERROR(dctx)); + + /* archive signature reference */ + s_addr = archive->map_addr; + s_ptr = s_addr; + + /* iterate, store meta data in library-friendly form */ + for (idx=0,longnamep=m->namestrs; idxmembers[idx]; + m->offsetv[idx] = m_ptr - s_ptr; + m->memberv[idx] = memberp; + + memberp->ar_file_header.ar_header_attr = attr; + + pe_ar_read_decimal_64( + arhdr->ar_time_date_stamp, + sizeof(arhdr->ar_time_date_stamp), + &memberp->ar_file_header.ar_time_date_stamp); + + pe_ar_read_decimal_32( + arhdr->ar_uid, + sizeof(arhdr->ar_uid), + &memberp->ar_file_header.ar_uid); + + pe_ar_read_decimal_32( + arhdr->ar_gid, + sizeof(arhdr->ar_gid), + &memberp->ar_file_header.ar_gid); + + pe_ar_read_octal( + arhdr->ar_file_mode, + sizeof(arhdr->ar_file_mode), + &memberp->ar_file_header.ar_file_mode); + + pe_ar_read_decimal_64( + arhdr->ar_file_size, + sizeof(arhdr->ar_file_size), + &memberp->ar_file_header.ar_file_size); + + memberp->ar_file_header.ar_member_name = longnamep; + + if (attr == (AR_HEADER_ATTR_FILE_ID | AR_HEADER_ATTR_SYSV)) { + if ((arhdr->ar_file_id[0] == '/') && (arhdr->ar_file_id[1] == '/')) { + *longnamep++ = '/'; + *longnamep++ = '/'; + longnamep++; + + } else if ((arhdr->ar_file_id[0] == '/') && (arhdr->ar_file_id[1] == 'S')) { + *longnamep++ = '/'; + *longnamep++ = 'S'; + *longnamep++ = 'Y'; + *longnamep++ = 'M'; + *longnamep++ = '6'; + *longnamep++ = '4'; + *longnamep++ = '/'; + longnamep++; + + } else if (arhdr->ar_file_id[0] == '/') { + *longnamep++ = '/'; + longnamep++; + + } else { + ch = arhdr->ar_file_id; + + for (; (*ch != '/'); ) + *longnamep++ = *ch++; + + longnamep++; + } + + } else if (attr == (AR_HEADER_ATTR_FILE_ID | AR_HEADER_ATTR_BSD)) { + ch = arhdr->ar_file_id; + fldcap = &ch[sizeof(arhdr->ar_file_id)]; + + for (; (char_file_id[1], + sizeof(arhdr->ar_file_id) - 1, + &nameoff); + + ch = arlongnames->ar_file_id; + ch += sizeof(*arlongnames); + ch += nameoff; + + for (; *ch && (*ch != '/') && (*ch != AR_OBJ_PADDING); ) + *longnamep++ = *ch++; + + longnamep++; + + } else if (attr == (AR_HEADER_ATTR_NAME_REF | AR_HEADER_ATTR_BSD)) { + pe_ar_read_decimal_64( + &arhdr->ar_file_id[3], + sizeof(arhdr->ar_file_id) - 3, + &namelen); + + mark = arhdr->ar_file_id; + mark += sizeof(*arhdr); + + memcpy(longnamep,mark,namelen); + + longnamep += namelen; + longnamep++; + } + + /* member raw header, object size, object data */ + mark = arhdr->ar_file_id; + mark += sizeof(*arhdr); + namelen = 0; + + if (attr == (AR_HEADER_ATTR_NAME_REF | AR_HEADER_ATTR_BSD)) { + pe_ar_read_decimal_64( + &arhdr->ar_file_id[3], + sizeof(arhdr->ar_file_id)-3, + &namelen); + + namelen += 1; + namelen |= 1; + namelen ^= 1; + + mark += namelen; + }; + + memberp->ar_member_data = arhdr; + memberp->ar_object_data = (void *)mark; + memberp->ar_object_size = memberp->ar_file_header.ar_file_size - namelen; + + /* member attribute */ + memberp->ar_member_attr = pe_ar_get_member_attr(memberp); + + /* pe/coff second linker member? */ + if ((idx == 1) && (memberp->ar_member_attr == AR_MEMBER_ATTR_ARMAP)) + if (hdrinfov[0].attr & AR_HEADER_ATTR_SYSV) + if (m->members[0].ar_member_attr == AR_MEMBER_ATTR_ARMAP) + if (attr & AR_HEADER_ATTR_SYSV) + memberp->ar_member_attr = AR_MEMBER_ATTR_LINKINFO; + + /* armap member must be the first */ + if ((memberp->ar_member_attr == AR_MEMBER_ATTR_ARMAP) && (idx > 0)) { + if (m->members[0].ar_member_attr == AR_MEMBER_ATTR_ARMAP) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_DUPLICATE_ARMAP_MEMBER)); + + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_MISPLACED_ARMAP_MEMBER)); + } + } + + /* number of archive members, including internal ones */ + m->nentries = nentries; + + /* primary armap (first linker member) */ + if (pe_ar_parse_primary_armap(dctx,m) < 0) + return pe_ar_free_archive_meta_impl( + m,PERK_NESTED_ERROR(dctx)); + + for (idx=0,ch=m->symstrs; idxarmaps.armap_nsyms; idx++) { + m->symstrv[idx] = ch; + ch += strlen(ch); + ch++; + } + + if (m->armaps.armap_common_32.ar_member) { + symrefs_32 = m->armaps.armap_symrefs_32; + + for (idx=0; idxarmaps.armap_nsyms; idx++) { + if (m->armaps.armap_common_32.ar_armap_attr & AR_ARMAP_ATTR_SYSV) + symrefs_32[idx].ar_name_offset = m->symstrv[idx] - m->symstrv[0]; + + if (!pe_archive_member_from_offset(m,symrefs_32[idx].ar_member_offset)) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_ARMAP_MEMBER_OFFSET)); + + if (symrefs_32[idx].ar_name_offset) { + ch = &m->symstrs[symrefs_32[idx].ar_name_offset]; + + if ((ch > m->symstrv[m->armaps.armap_nsyms - 1]) || *--ch) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_ARMAP_NAME_OFFSET)); + } + + } + } + + if (m->armaps.armap_common_64.ar_member) { + symrefs_64 = m->armaps.armap_symrefs_64; + + for (idx=0; idxarmaps.armap_nsyms; idx++) { + if (m->armaps.armap_common_64.ar_armap_attr & AR_ARMAP_ATTR_SYSV) + symrefs_64[idx].ar_name_offset = m->symstrv[idx] - m->symstrv[0]; + + if (!pe_archive_member_from_offset(m,symrefs_64[idx].ar_member_offset)) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_ARMAP_MEMBER_OFFSET)); + + if (symrefs_64[idx].ar_name_offset) { + ch = &m->symstrs[symrefs_64[idx].ar_name_offset]; + + if ((ch > m->symstrv[m->armaps.armap_nsyms - 1]) || *--ch) + return pe_ar_free_archive_meta_impl( + m,PERK_CUSTOM_ERROR( + dctx, + PERK_ERR_AR_INVALID_ARMAP_NAME_OFFSET)); + } + + } + } + + /* number of public archive members */ + for (idx=0,nmembers=0; idxmemberv[idx]->ar_member_attr) { + case AR_MEMBER_ATTR_ARMAP: + case AR_MEMBER_ATTR_LINKINFO: + case AR_MEMBER_ATTR_NAMESTRS: + break; + + default: + nmembers++; + } + } + + if (m->armaps.armap_common_32.ar_member) + m->armaps.armap_common_32.ar_num_of_members = nmembers; + + if (m->armaps.armap_common_64.ar_member) + m->armaps.armap_common_64.ar_num_of_members = nmembers; + + /* pe/coff armap attributes (second linker member) */ + (void)m->armeta.a_armap_pecoff; + + /* reference to the long names member */ + if (arlongnames) + for (idx=0; idxarmeta.a_arref_longnames; idx++) + if (m->memberv[idx]->ar_member_data == arlongnames) + m->armeta.a_arref_longnames = m->memberv[idx]; + + /* common binary format (information only) */ + for (idx=0,nmembers=0; idxmemberv[idx]->ar_member_attr == AR_MEMBER_ATTR_OBJECT) { + if (m->ofmtattr && (m->ofmtattr != m->memberv[idx]->ar_object_attr)) { + m->ofmtattr = 0; + idx = nentries; + } else if (!m->ofmtattr) { + m->ofmtattr = m->memberv[idx]->ar_object_attr; + } + } + } + + /* member vector */ + m->armeta.a_memberv = m->memberv; + + /* all done */ + if (m->hdrinfov) { + free(m->hdrinfov); + m->hdrinfov = 0; + } + + *meta = &m->armeta; + + return 0; +} + +void pe_ar_free_archive_meta(struct pe_archive_meta * meta) +{ + struct pe_archive_meta_impl * m; + + if (meta) { + m = pe_archive_meta_ictx(meta); + pe_ar_free_archive_meta_impl(m,0); + } +} -- cgit v1.2.3