update to ida 7.6, add builds
This commit is contained in:
149
idasdk76/ldr/ar/aixar.hpp
Normal file
149
idasdk76/ldr/ar/aixar.hpp
Normal file
@@ -0,0 +1,149 @@
|
||||
/* IBM_PROLOG_BEGIN_TAG */
|
||||
/* This is an automatically generated prolog. */
|
||||
/* */
|
||||
/* bos420 src/bos/usr/include/ar.h */
|
||||
/* */
|
||||
/* Licensed Materials - Property of IBM */
|
||||
/* */
|
||||
/* (C) COPYRIGHT International Business Machines Corp. 1989,1995 */
|
||||
/* All Rights Reserved */
|
||||
/* */
|
||||
/* US Government Users Restricted Rights - Use, duplication or */
|
||||
/* disclosure restricted by GSA ADP Schedule Contract with IBM Corp. */
|
||||
/* */
|
||||
/* IBM_PROLOG_END_TAG */
|
||||
/* @(#)25 1.8 src/bos/usr/include/ar.h, cmdar, bos420, 9613T 6/16/90 00:07:48 */
|
||||
/* ar.h 5.1 - 86/12/09 - 06:03:39 */
|
||||
#ifndef _H_AR
|
||||
#define _H_AR
|
||||
#pragma pack(push, 1)
|
||||
/*
|
||||
* COMPONENT_NAME: CMDAR
|
||||
*
|
||||
* FUNCTIONS: none
|
||||
*
|
||||
* ORIGINS: 27, 3
|
||||
*
|
||||
* (C) COPYRIGHT International Business Machines Corp. 1989
|
||||
* All Rights Reserved
|
||||
* Licensed Materials - Property of IBM
|
||||
*
|
||||
* US Government Users Restricted Rights - Use, duplication or
|
||||
* disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
|
||||
*/
|
||||
|
||||
/* AIX INDEXED ARCHIVE FORMAT
|
||||
*
|
||||
* ARCHIVE File Organization:
|
||||
* _____________________________________________
|
||||
* |__________FIXED HEADER "fl_hdr"______________|
|
||||
* +--- | |
|
||||
* | |__________ARCHIVE_FILE_MEMBER_1______________|
|
||||
* +--> | |
|
||||
* | Archive Member Header "ar_hdr" |
|
||||
* +--- |.............................................| <--+
|
||||
* | | Member Contents | |
|
||||
* | |_____________________________________________| |
|
||||
* | |________ARCHIVE_FILE_MEMBER_2________________| |
|
||||
* +--> | | ---+
|
||||
* | Archive Member Header "ar_hdr" |
|
||||
* +--- |.............................................| <--+
|
||||
* | | Member Contents | |
|
||||
* | |_____________________________________________| |
|
||||
* | | . . . | |
|
||||
* . | . . . | .
|
||||
* . | . . . | .
|
||||
* . |_____________________________________________| .
|
||||
* | |________ARCHIVE_FILE_MEMBER_n-1______________| |
|
||||
* +--> | | ---+
|
||||
* | Archive Member Header "ar_hdr" |
|
||||
* +--- |.............................................| <--+
|
||||
* | | Member Contents | |
|
||||
* | | (Member Table, always present) | |
|
||||
* | |_____________________________________________| |
|
||||
* | |_____________________________________________| |
|
||||
* | |________ARCHIVE_FILE_MEMBER_n________________| |
|
||||
* | | | |
|
||||
* +--> | Archive Member Header "ar_hdr" | ---+
|
||||
* |.............................................|
|
||||
* | Member Contents |
|
||||
* | (Global Symbol Table if present) |
|
||||
* |_____________________________________________|
|
||||
*
|
||||
*/
|
||||
|
||||
#define AIAMAG "<aiaff>\n"
|
||||
#define AIAMAGBIG "<bigaf>\n"
|
||||
#define SAIAMAG 8
|
||||
#define AIAFMAG "`\n"
|
||||
|
||||
struct fl_hdr /* archive fixed length header */
|
||||
{
|
||||
char fl_magic[SAIAMAG]; /* Archive magic string */
|
||||
char fl_memoff[20]; /*Offset to member table */
|
||||
char fl_gstoff[20]; /*Offset to global symbol table */
|
||||
char fl_gst64off[20]; /*Offset global symbol table for 64-bit objects */
|
||||
char fl_fstmoff[20]; /*Offset to first archive member */
|
||||
char fl_lstmoff[20]; /*Offset to last archive member */
|
||||
char fl_freeoff[20]; /*Offset to first mem on free list */
|
||||
};
|
||||
|
||||
struct aix_ar_hdr /* archive file member header - printable ascii */
|
||||
{
|
||||
char ar_size[20]; /* File member size - decimal */
|
||||
char ar_nxtmem[20]; /* Next member offset-decimal */
|
||||
char ar_prvmem[20]; /* Previous member offset-dec */
|
||||
char ar_date[12]; /* File member date-decimal */
|
||||
char ar_uid[12]; /* File member userid-decimal */
|
||||
char ar_gid[12]; /* File member group id-decimal */
|
||||
char ar_mode[12]; /* File member mode-octal */
|
||||
char ar_namlen[4]; /* File member name length-dec */
|
||||
#if 0
|
||||
union
|
||||
{
|
||||
char ar_name[2]; /* variable length member name */
|
||||
char ar_fmag[2]; /* AIAFMAG - string to end header */
|
||||
} _ar_name; /* and variable length name */
|
||||
#endif
|
||||
};
|
||||
|
||||
struct fl_hdr_small /* archive fixed length header (prior to Version 4.3) */
|
||||
{
|
||||
char fl_magic[SAIAMAG]; /* Archive file magic string */
|
||||
char fl_memoff[12]; /* Offset to member table */
|
||||
char fl_gstoff[12]; /* Offset to global symbol table */
|
||||
char fl_fstmoff[12]; /* Offset to first archive member */
|
||||
char fl_lstmoff[12]; /* Offset to last archive member */
|
||||
char fl_freeoff[12]; /* Offset to first mem on free list */
|
||||
};
|
||||
|
||||
struct aix_ar_hdr_small /* archive file member header - printable ascii */
|
||||
{
|
||||
char ar_size[12]; /* file member size - decimal */
|
||||
char ar_nxtmem[12]; /* pointer to next member - decimal */
|
||||
char ar_prvmem[12]; /* pointer to previous member - decimal */
|
||||
char ar_date[12]; /* file member date - decimal */
|
||||
char ar_uid[12]; /* file member user id - decimal */
|
||||
char ar_gid[12]; /* file member group id - decimal */
|
||||
char ar_mode[12]; /* file member mode - octal */
|
||||
char ar_namlen[4]; /* file member name length - decimal */
|
||||
#if 0
|
||||
union
|
||||
{
|
||||
char ar_name[2]; /* variable length member name */
|
||||
char ar_fmag[2]; /* AIAFMAG - string to end header */
|
||||
} _ar_name; /* and variable length name */
|
||||
#endif
|
||||
};
|
||||
/*
|
||||
* Note: 'ar_namlen' contains the length of the member name which
|
||||
* may be up to 255 chars. The character string containing
|
||||
* the name begins at '_ar_name.ar_name'. The terminating
|
||||
* string AIAFMAG, is only cosmetic. File member contents begin
|
||||
* at the first even byte boundary past 'header position +
|
||||
* sizeof(struct ar_hdr) + ar_namlen', and continue for
|
||||
* 'ar_size' bytes.
|
||||
*/
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif /* _H_AR */
|
||||
113
idasdk76/ldr/ar/ar.hpp
Normal file
113
idasdk76/ldr/ar/ar.hpp
Normal file
@@ -0,0 +1,113 @@
|
||||
/* So far this is correct for BSDish archives. Don't forget that
|
||||
files must begin on an even byte boundary. */
|
||||
|
||||
#ifndef __AR_H__
|
||||
#define __AR_H__
|
||||
#pragma pack(push, 1)
|
||||
|
||||
/* Note that the usual '\n' in magic strings may translate to different
|
||||
characters, as allowed by ANSI. '\012' has a fixed value, and remains
|
||||
compatible with existing BSDish archives. */
|
||||
|
||||
#define ARMAG "!<arch>\012" /* For COFF and a.out archives */
|
||||
#define ARMAGB "!<bout>\012" /* For b.out archives */
|
||||
#define ARMAGE "!<elf_>\012" /* For ELF archives */
|
||||
#define SARMAG 8
|
||||
#define ARFMAG "`\012"
|
||||
|
||||
/* The ar_date field of the armap (__.SYMDEF) member of an archive
|
||||
must be greater than the modified date of the entire file, or
|
||||
BSD-derived linkers complain. We originally write the ar_date with
|
||||
this offset from the real file's mod-time. After finishing the
|
||||
file, we rewrite ar_date if it's not still greater than the mod date. */
|
||||
|
||||
#define ARMAP_TIME_OFFSET 60
|
||||
|
||||
struct ar_hdr
|
||||
{
|
||||
char ar_name[16]; /* name of this member */
|
||||
char ar_date[12]; /* file mtime */
|
||||
char ar_uid[6]; /* owner uid; printed as decimal */
|
||||
char ar_gid[6]; /* owner gid; printed as decimal */
|
||||
char ar_mode[8]; /* file mode, printed as octal */
|
||||
char ar_size[10]; /* file size, printed as decimal */
|
||||
char ar_fmag[2]; /* should contain ARFMAG */
|
||||
};
|
||||
|
||||
#define AR_EFMT1 "#1/" /* extended format #1: BSD/Apple archives */
|
||||
|
||||
// ig. get all module names from ar
|
||||
|
||||
int process_ar(
|
||||
char *libfile, /* return 0 - ok */
|
||||
int (*_callback)(
|
||||
void *ud,
|
||||
int32 offset,
|
||||
int method,
|
||||
uint32 csize,
|
||||
uint32 ucsize,
|
||||
uint32 attributes,
|
||||
const char *filename),
|
||||
void *ud);
|
||||
|
||||
// The first linker member has the following format. This information appears after the
|
||||
// header:
|
||||
//
|
||||
// Offset Size Field Description
|
||||
// 0 4 Number of Symbols Unsigned long containing the number of symbols indexed.
|
||||
// This number is stored in big-endian format. Each object-file member
|
||||
// typically defines one or more external symbols.
|
||||
// 4 4*n Offsets Array of file offsets to archive member headers, in which n is
|
||||
// equal to Number of Symbols. Each number in the array is an unsigned long
|
||||
// stored in big-endian format. For each symbol named in the String Table,
|
||||
// the corresponding element in the Offsets array gives the location of the
|
||||
// archive member that contains the symbol.
|
||||
// * * String Table Series of null-terminated strings that name all the symbols
|
||||
// in the directory. Each string begins immediately after the null character
|
||||
// in the previous string. The number of strings must be equal to the value
|
||||
// of the Number of Symbols fields.
|
||||
//
|
||||
// -----------------------------
|
||||
// The second linker member has the name '\' as does the first linker member. Although
|
||||
// both the linker members provide a directory of symbols and archive members that contain
|
||||
// them, the second linker member is used in preference to the first by all current
|
||||
// linkers. The second linker member includes symbol names in lexical order, which enables
|
||||
// faster searching by name.
|
||||
//
|
||||
// The first second member has the following format. This information appears after the
|
||||
// header:
|
||||
//
|
||||
// Offset Size Field Description
|
||||
// 0 4 Number of Members Unsigned long containing the number of archive members.
|
||||
// 4 4*m Offsets Array of file offsets to archive member headers, arranged in
|
||||
// ascending order. Each offset is an unsigned long. The number m is equal
|
||||
// to the value of the Number of Members field.
|
||||
// * 4 Number of Symbols Unsigned long containing the number of symbols indexed.
|
||||
// Each object-file member typically defines one or more external symbols.
|
||||
// * 2*n Indices Array of 1-based indices (unsigned short) which map symbol names
|
||||
// to archive member offsets. The number n is equal to Number of Symbols.
|
||||
// For each symbol named in the String Table, the corresponding element in
|
||||
// the Indices array gives an index into the Offsets array. The Offsets
|
||||
// array, in turn, gives the location of the archive member that contains
|
||||
// the symbol.
|
||||
// * * String Table Series of null-terminated strings that name all the symbols
|
||||
// in the directory. Each string begins immediately after the null byte in
|
||||
// the previous string. The number of strings must be equal to the value of
|
||||
// the Number of Symbols fields. This table lists all the symbol names in
|
||||
// ascending lexical order.
|
||||
//
|
||||
// //-----------------------------
|
||||
// The name of the longnames member is '\\'. The longnames member is a series of
|
||||
// strings of archive member names. A name appears here only when there is insufficient
|
||||
// room in the Name field (16 bytes). The longnames member can be empty, though its
|
||||
// header must appear.
|
||||
//
|
||||
// The strings are null-terminated. Each string begins immediately after the null byte
|
||||
// in the previous string.
|
||||
//
|
||||
|
||||
bool is_ar_file(linput_t *li, qoff64_t offset, bool include_aix);
|
||||
|
||||
#pragma pack(pop)
|
||||
#endif /* __AR_H__ */
|
||||
|
||||
238
idasdk76/ldr/ar/arcmn.cpp
Normal file
238
idasdk76/ldr/ar/arcmn.cpp
Normal file
@@ -0,0 +1,238 @@
|
||||
|
||||
#include <diskio.hpp>
|
||||
|
||||
#define MAGICLEN ((SARMAG > SAIAMAG) ? SARMAG : SAIAMAG)
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
bool is_ar_file(linput_t *li, qoff64_t offset, bool include_aix)
|
||||
{
|
||||
char magic[MAGICLEN];
|
||||
qlseek(li, offset);
|
||||
if ( qlread(li, magic, sizeof(magic)) != sizeof(magic) )
|
||||
return false;
|
||||
return memcmp(magic, ARMAG, SARMAG) == 0
|
||||
|| memcmp(magic, ARMAGB, SARMAG) == 0
|
||||
|| memcmp(magic, ARMAGE, SARMAG) == 0
|
||||
|| include_aix
|
||||
&& (memcmp(magic,AIAMAG,SAIAMAG) == 0
|
||||
|| memcmp(magic,AIAMAGBIG,SAIAMAG) == 0);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static char *get_msft_module_name(
|
||||
const char *ahname,
|
||||
const char *ahend,
|
||||
char *name,
|
||||
size_t size)
|
||||
{
|
||||
if ( size == 0 )
|
||||
return NULL;
|
||||
char *ptr = name;
|
||||
for ( size_t i=0; ahname < ahend; i++,ptr++ )
|
||||
{
|
||||
char chr = *ahname++;
|
||||
if ( chr == '\n' || i == size-1 )
|
||||
chr = '\0';
|
||||
*ptr = chr;
|
||||
if ( chr == '\0' )
|
||||
break;
|
||||
}
|
||||
while ( ptr > name && qisspace(ptr[-1]) )
|
||||
*--ptr = '\0';
|
||||
if ( ptr > name && ptr[-1] == '/' )
|
||||
ptr[-1] = '\0';
|
||||
return name;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
static const char *get_ar_modname(
|
||||
const char *lnames,
|
||||
const char *end,
|
||||
const char *name,
|
||||
char *buf,
|
||||
size_t bufsize)
|
||||
{
|
||||
if ( lnames != NULL && *name == '/' )
|
||||
{
|
||||
name++;
|
||||
size_t off = size_t(atol(name));
|
||||
while ( qisdigit(*name) )
|
||||
name++;
|
||||
if ( *name == '\0' )
|
||||
{
|
||||
if ( lnames+off < lnames )
|
||||
return qstrncpy(buf, "?", bufsize);
|
||||
return get_msft_module_name(lnames+off, end, buf, bufsize);
|
||||
}
|
||||
}
|
||||
return qstrncpy(buf, name, bufsize);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
// return codes:
|
||||
// 0: ok
|
||||
// 1: no input file
|
||||
// 2: read error
|
||||
// 3: bad archive
|
||||
// 4: not enough memory
|
||||
// 5: maxpos reached
|
||||
|
||||
struct ar_visitor_t
|
||||
{
|
||||
virtual ssize_t idaapi visit_ar_module(
|
||||
qoff64_t offset,
|
||||
ar_hdr *ah,
|
||||
uint64 size,
|
||||
char *filename) = 0;
|
||||
};
|
||||
|
||||
// Enumerate modules in AR archive.
|
||||
// \param maxpos Max position in file. Typically is used when
|
||||
// archive is embedded within other file.
|
||||
ssize_t enum_ar_contents(linput_t *li, ar_visitor_t &av, int32 maxpos = -1)
|
||||
{
|
||||
ssize_t code = 0;
|
||||
char *names = NULL;
|
||||
size_t names_size = 0;
|
||||
while ( true )
|
||||
{
|
||||
ar_hdr ah;
|
||||
qoff64_t filepos = qltell(li);
|
||||
if ( filepos & 1 )
|
||||
qlseek(li, filepos+1);
|
||||
if ( maxpos > -1 && filepos >= maxpos )
|
||||
{
|
||||
code = 5;
|
||||
break;
|
||||
}
|
||||
ssize_t bytes = qlread(li, &ah, sizeof(ah));
|
||||
if ( bytes == 0 )
|
||||
break; // end of archive, no error
|
||||
if ( bytes != sizeof(ah) )
|
||||
{
|
||||
code = 2; // read error
|
||||
break;
|
||||
}
|
||||
if ( memcmp(ah.ar_fmag, ARFMAG, sizeof(ah.ar_fmag)) != 0 )
|
||||
{
|
||||
code = 3; // bad archive
|
||||
break;
|
||||
}
|
||||
char name[sizeof(ah.ar_name)+1];
|
||||
get_msft_module_name(ah.ar_name, ah.ar_name+sizeof(ah.ar_name), name, sizeof(name));
|
||||
uint64 size = qatoll(ah.ar_size);
|
||||
filepos = qltell(li);
|
||||
if ( names == NULL && name[0] == '/' && name[1] == '\0' )
|
||||
{
|
||||
if ( size != 0 )
|
||||
{
|
||||
names = (char *)qalloc(size);
|
||||
if ( names == NULL )
|
||||
{
|
||||
code = 4; // not enough memory
|
||||
break;
|
||||
}
|
||||
names_size = size;
|
||||
if ( qlread(li, names, size) != size )
|
||||
{
|
||||
code = 2; // read error
|
||||
break;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if ( memcmp(name, AR_EFMT1, 3) == 0 )
|
||||
{
|
||||
// BSD/Apple archive: the length of long name follows
|
||||
// #1/nnn
|
||||
size_t extralen = size_t(atol(name+3));
|
||||
char *modname = (char *)qalloc(extralen+1);
|
||||
if ( modname == NULL )
|
||||
{
|
||||
code = 4; // not enough memory
|
||||
break;
|
||||
}
|
||||
if ( qlread(li, modname, extralen) != extralen )
|
||||
{
|
||||
code = 2; // read error
|
||||
break;
|
||||
}
|
||||
modname[extralen]='\0';
|
||||
|
||||
// skip special files
|
||||
if ( !strneq(modname, "__.SYMDEF", sizeof("__.SYMDEF")-1) )
|
||||
{
|
||||
code = av.visit_ar_module(qoff64_t(filepos+extralen), &ah, size-extralen, modname);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
}
|
||||
qfree(modname);
|
||||
}
|
||||
else if ( name[0] != '\0' )
|
||||
{
|
||||
char modname[MAXSTR];
|
||||
get_ar_modname(names, names+names_size, name, modname, sizeof(modname));
|
||||
code = av.visit_ar_module(filepos, &ah, size, modname);
|
||||
if ( code != 0 )
|
||||
break;
|
||||
}
|
||||
qlseek(li, qoff64_t(filepos+size));
|
||||
}
|
||||
qfree(names);
|
||||
return code;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// convert small archive header to big one
|
||||
bool upgrade_aix_fl_hdr(fl_hdr *fh, const fl_hdr_small *fh_small)
|
||||
{
|
||||
if ( memcmp(fh_small->fl_magic, AIAMAG, SAIAMAG) != 0 )
|
||||
return false; // not small archive
|
||||
qstrncpy(fh->fl_memoff, fh_small->fl_memoff, sizeof(fh->fl_memoff));
|
||||
qstrncpy(fh->fl_gstoff, fh_small->fl_gstoff, sizeof(fh->fl_gstoff));
|
||||
fh->fl_gst64off[0] = '\0';
|
||||
qstrncpy(fh->fl_fstmoff, fh_small->fl_fstmoff, sizeof(fh->fl_fstmoff));
|
||||
qstrncpy(fh->fl_lstmoff, fh_small->fl_lstmoff, sizeof(fh->fl_lstmoff));
|
||||
qstrncpy(fh->fl_freeoff, fh_small->fl_freeoff, sizeof(fh->fl_freeoff));
|
||||
return true;
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool read_aix_fl_hdr(fl_hdr *fh, linput_t *li)
|
||||
{
|
||||
size_t nread = qlread(li, fh, sizeof(*fh));
|
||||
if ( nread == sizeof(*fh) && memcmp(fh->fl_magic, AIAMAGBIG, SAIAMAG) == 0 )
|
||||
return true;
|
||||
if ( nread < sizeof(fl_hdr_small) )
|
||||
return false;
|
||||
fl_hdr_small fh_small;
|
||||
memcpy(&fh_small, fh, sizeof(fh_small)); //-V512 call of the 'memcpy' function will lead to underflow of the buffer
|
||||
return upgrade_aix_fl_hdr(fh, &fh_small);
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// convert small member header to big one
|
||||
void upgrade_aix_ar_hdr(aix_ar_hdr *ah, const aix_ar_hdr_small *ah_small)
|
||||
{
|
||||
qstrncpy(ah->ar_size, ah_small->ar_size, sizeof(ah->ar_size));
|
||||
qstrncpy(ah->ar_nxtmem, ah_small->ar_nxtmem, sizeof(ah->ar_nxtmem));
|
||||
qstrncpy(ah->ar_prvmem, ah_small->ar_prvmem, sizeof(ah->ar_prvmem));
|
||||
qstrncpy(ah->ar_date, ah_small->ar_date, sizeof(ah->ar_date));
|
||||
qstrncpy(ah->ar_uid, ah_small->ar_uid, sizeof(ah->ar_uid));
|
||||
qstrncpy(ah->ar_gid, ah_small->ar_gid, sizeof(ah->ar_gid));
|
||||
qstrncpy(ah->ar_mode, ah_small->ar_mode, sizeof(ah->ar_mode));
|
||||
qstrncpy(ah->ar_namlen, ah_small->ar_namlen, sizeof(ah->ar_namlen));
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
bool read_aix_ar_hdr(aix_ar_hdr *ah, const fl_hdr *fh, linput_t *li)
|
||||
{
|
||||
if ( memcmp(fh->fl_magic, AIAMAGBIG, SAIAMAG) == 0 )
|
||||
return qlread(li, ah, sizeof(*ah)) == sizeof(*ah);
|
||||
aix_ar_hdr_small ah_small;
|
||||
if ( qlread(li, &ah_small, sizeof(ah_small)) != sizeof(ah_small) )
|
||||
return false;
|
||||
upgrade_aix_ar_hdr(ah, &ah_small);
|
||||
return true;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user