mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
coff moved to uppsrc2
git-svn-id: svn://ultimatepp.org/upp/trunk@7711 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
9ab355b225
commit
c863f38e22
38 changed files with 8801 additions and 0 deletions
22
uppsrc2/coff/Copying
Normal file
22
uppsrc2/coff/Copying
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 1998, 2014, The U++ Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
ERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
22
uppsrc2/coff/binobj/Copying
Normal file
22
uppsrc2/coff/binobj/Copying
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 1998, 2014, The U++ Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
ERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
505
uppsrc2/coff/binobj/binobj.cpp
Normal file
505
uppsrc2/coff/binobj/binobj.cpp
Normal file
|
|
@ -0,0 +1,505 @@
|
|||
#include "binobj.h"
|
||||
#include <plugin/z/z.h>
|
||||
#include <plugin/bz2/bz2.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
BinObjInfo::BinObjInfo()
|
||||
{
|
||||
}
|
||||
|
||||
void BinObjInfo::Parse(CParser& binscript, String base_dir)
|
||||
{
|
||||
while(!binscript.IsEof()) {
|
||||
String binid = binscript.ReadId();
|
||||
bool ba = (binid == "BINARY_ARRAY");
|
||||
bool bm = (binid == "BINARY_MASK");
|
||||
if(binid == "BINARY" || ba || bm) {
|
||||
binscript.PassChar('(');
|
||||
Block blk;
|
||||
blk.scriptline = binscript.GetLine();
|
||||
blk.ident = binscript.ReadId();
|
||||
ArrayMap<int, Block>& brow = blocks.GetAdd(blk.ident);
|
||||
binscript.PassChar(',');
|
||||
blk.index = -1;
|
||||
if(ba) {
|
||||
blk.flags |= Block::FLG_ARRAY;
|
||||
blk.index = binscript.ReadInt();
|
||||
if(blk.index < 0 || blk.index > 1000000)
|
||||
binscript.ThrowError(NFormat("invalid array index: %d", blk.index));
|
||||
binscript.PassChar(',');
|
||||
}
|
||||
else if(bm) {
|
||||
blk.flags |= Block::FLG_MASK;
|
||||
blk.index = brow.GetCount();
|
||||
}
|
||||
String file = binscript.ReadString();
|
||||
if(binscript.Id("ZIP"))
|
||||
blk.encoding = Block::ENC_ZIP;
|
||||
else if(binscript.Id("BZ2"))
|
||||
blk.encoding = Block::ENC_BZ2;
|
||||
binscript.PassChar(')');
|
||||
FindFile ff;
|
||||
String searchpath = NormalizePath(file, base_dir);
|
||||
String searchdir = GetFileDirectory(searchpath);
|
||||
Vector<String> files;
|
||||
Vector<int64> lengths;
|
||||
if(ff.Search(searchpath))
|
||||
do
|
||||
if(ff.IsFile()) {
|
||||
files.Add(ff.GetName());
|
||||
lengths.Add(ff.GetLength());
|
||||
}
|
||||
while(ff.Next());
|
||||
if(files.IsEmpty())
|
||||
binscript.ThrowError(NFormat("'%s' not found or not a file", file));
|
||||
if(!(blk.flags & Block::FLG_MASK) && files.GetCount() > 1)
|
||||
binscript.ThrowError(NFormat("Multiple files found (e.g. %s, %s) in single file mode", files[0], files[1]));
|
||||
IndexSort(files, lengths);
|
||||
for(int i = 0; i < files.GetCount(); i++) {
|
||||
blk.file = AppendFileName(searchdir, files[i]);
|
||||
blk.length = (int)lengths[i];
|
||||
int f = brow.Find(blk.index);
|
||||
if(f >= 0)
|
||||
binscript.ThrowError(NFormat("%s[%d] already seen at line %d", blk.ident, blk.index, brow[f].scriptline));
|
||||
if(blk.index < 0 && !brow.IsEmpty() || blk.index >= 0 && !brow.IsEmpty() && brow[0].index < 0)
|
||||
binscript.ThrowError(NFormat("%s: mixing non-array and array elements", blk.ident));
|
||||
brow.Add(blk.index, blk);
|
||||
if(!(blk.flags & Block::FLG_MASK))
|
||||
break;
|
||||
blk.index++;
|
||||
}
|
||||
}
|
||||
else
|
||||
binscript.ThrowError("binary script item identifier expected");
|
||||
}
|
||||
}
|
||||
|
||||
class BinObj : public BinObjInfo {
|
||||
public:
|
||||
BinObj(Callback1<String> WhenConsole);
|
||||
|
||||
void Run(String objectfile, CParser& binscript, String base_dir);
|
||||
|
||||
public:
|
||||
Callback1<String> WhenConsole;
|
||||
|
||||
private:
|
||||
void PrepareSymbolTable(String binfile);
|
||||
void PrepareMetaData();
|
||||
void FixAuxSymbols(int data_size);
|
||||
void WriteFile(String objectfile);
|
||||
|
||||
int AddSymbol(COFF_IMAGE_SYMBOL& sym, const char *name);
|
||||
int AddMetaData(int value, int reloc_section = -1);
|
||||
|
||||
static int Align(int len) { return (len + 3) & -4; }
|
||||
|
||||
private:
|
||||
Vector<byte> metadata;
|
||||
// int data_size;
|
||||
Vector<byte> relocations;
|
||||
Vector<byte> symbol_table;
|
||||
Vector<byte> symbol_table_strtbl;
|
||||
|
||||
enum {
|
||||
SCN_COMDAT,
|
||||
SCN_METADATA,
|
||||
SCN_DATA,
|
||||
};
|
||||
|
||||
int aux_metadata_scn;
|
||||
int aux_data_scn;
|
||||
int symtbl_metasec;
|
||||
int symtbl_datasec;
|
||||
};
|
||||
|
||||
static const char metadata_secn[] = ".data$BM";
|
||||
static const char data_secn[] = ".data$BD";
|
||||
|
||||
BinObj::BinObj(Callback1<String> WhenConsole_)
|
||||
: WhenConsole(WhenConsole_)
|
||||
{
|
||||
symbol_table_strtbl.SetCountR(4);
|
||||
}
|
||||
|
||||
void BinObj::Run(String objectfile, CParser& binscript, String base_dir)
|
||||
{
|
||||
Parse(binscript, base_dir);
|
||||
PrepareSymbolTable(binscript.GetFileName());
|
||||
PrepareMetaData();
|
||||
WriteFile(objectfile);
|
||||
}
|
||||
|
||||
void BinObj::PrepareMetaData()
|
||||
{
|
||||
// data_size = 0;
|
||||
for(int i = 0; i < blocks.GetCount(); i++) {
|
||||
String ident;
|
||||
ident << '_' << blocks.GetKey(i);
|
||||
ArrayMap<int, Block>& belem = blocks[i];
|
||||
int flags = belem[0].flags;
|
||||
if(flags & (Block::FLG_ARRAY | Block::FLG_MASK)) {
|
||||
int count = Max(belem.GetKeys()) + 1;
|
||||
Vector<Block *> blockref;
|
||||
blockref.SetCount(count, 0);
|
||||
for(int a = 0; a < belem.GetCount(); a++) {
|
||||
Block& b = belem[a];
|
||||
// b.offset = data_size;
|
||||
blockref[b.index] = &b;
|
||||
// data_size += Align(b.length + 1);
|
||||
}
|
||||
COFF_IMAGE_SYMBOL countsym;
|
||||
Zero(countsym);
|
||||
countsym.Value = AddMetaData(count);
|
||||
countsym.SectionNumber = SCN_METADATA;
|
||||
countsym.StorageClass = COFF_IMAGE_SYM_CLASS_EXTERNAL;
|
||||
countsym.Type = 4;
|
||||
AddSymbol(countsym, ident + "_count");
|
||||
COFF_IMAGE_SYMBOL lensym;
|
||||
Zero(lensym);
|
||||
lensym.Value = metadata.GetCount();
|
||||
lensym.SectionNumber = SCN_METADATA;
|
||||
lensym.StorageClass = COFF_IMAGE_SYM_CLASS_EXTERNAL;
|
||||
lensym.Type = COFF_IMAGE_SYM_TYPE_INT + 256 * COFF_IMAGE_SYM_DTYPE_ARRAY;
|
||||
AddSymbol(lensym, ident + "_length");
|
||||
for(int a = 0; a < count; a++) {
|
||||
if(blockref[a])
|
||||
blockref[a]->len_meta_offset = metadata.GetCount();
|
||||
AddMetaData(-1);
|
||||
}
|
||||
COFF_IMAGE_SYMBOL ptrsym;
|
||||
Zero(ptrsym);
|
||||
ptrsym.Value = metadata.GetCount();
|
||||
ptrsym.SectionNumber = SCN_METADATA;
|
||||
ptrsym.StorageClass = COFF_IMAGE_SYM_CLASS_EXTERNAL;
|
||||
ptrsym.Type = COFF_IMAGE_SYM_TYPE_INT + 256 * COFF_IMAGE_SYM_DTYPE_ARRAY;
|
||||
AddSymbol(ptrsym, ident);
|
||||
for(int a = 0; a < count; a++) {
|
||||
if(blockref[a])
|
||||
blockref[a]->off_meta_offset = metadata.GetCount();
|
||||
AddMetaData(0, blockref[a] ? symtbl_datasec : 0);
|
||||
}
|
||||
if(flags & Block::FLG_MASK) {
|
||||
Vector<int> fn_offsets;
|
||||
fn_offsets.SetCount(count);
|
||||
for(int a = 0; a < count; a++) {
|
||||
String fn;
|
||||
if(blockref[a])
|
||||
fn = GetFileName(blockref[a]->file);
|
||||
int pos = metadata.GetCount();
|
||||
fn_offsets[a] = pos;
|
||||
metadata.SetCountR(pos + fn.GetLength() + 1);
|
||||
memcpy(&metadata[pos], fn, fn.GetLength() + 1);
|
||||
}
|
||||
metadata.SetCountR(Align(metadata.GetCount()), 0);
|
||||
COFF_IMAGE_SYMBOL filesym;
|
||||
Zero(filesym);
|
||||
filesym.Value = metadata.GetCount();
|
||||
filesym.SectionNumber = SCN_METADATA;
|
||||
filesym.StorageClass = COFF_IMAGE_SYM_CLASS_EXTERNAL;
|
||||
filesym.Type = COFF_IMAGE_SYM_TYPE_INT + 256 * COFF_IMAGE_SYM_DTYPE_ARRAY;
|
||||
AddSymbol(filesym, ident + "_files");
|
||||
for(int a = 0; a < count; a++)
|
||||
AddMetaData(fn_offsets[a], symtbl_metasec);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Block& b = belem[0];
|
||||
COFF_IMAGE_SYMBOL lensym;
|
||||
Zero(lensym);
|
||||
b.len_meta_offset = metadata.GetCount();
|
||||
lensym.Value = AddMetaData(b.length);
|
||||
lensym.SectionNumber = SCN_METADATA;
|
||||
lensym.StorageClass = COFF_IMAGE_SYM_CLASS_EXTERNAL;
|
||||
lensym.Type = COFF_IMAGE_SYM_TYPE_INT;
|
||||
AddSymbol(lensym, ident + "_length");
|
||||
COFF_IMAGE_SYMBOL datasym;
|
||||
Zero(datasym);
|
||||
b.off_meta_offset = metadata.GetCount();
|
||||
datasym.Value = AddMetaData(0, symtbl_datasec);
|
||||
datasym.SectionNumber = SCN_METADATA;
|
||||
datasym.StorageClass = COFF_IMAGE_SYM_CLASS_EXTERNAL;
|
||||
datasym.Type = COFF_IMAGE_SYM_TYPE_INT;
|
||||
AddSymbol(datasym, ident);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BinObj::PrepareSymbolTable(String binfile)
|
||||
{
|
||||
{ // FILE
|
||||
COFF_IMAGE_SYMBOL filesym;
|
||||
Zero(filesym);
|
||||
filesym.SectionNumber = -2;
|
||||
filesym.StorageClass = COFF_IMAGE_SYM_CLASS_FILE;
|
||||
filesym.NumberOfAuxSymbols = int(binfile.GetLength() / sizeof(COFF_IMAGE_SYMBOL) + 1);
|
||||
memcpy(symbol_table.GetIter(AddSymbol(filesym, ".file")), binfile, binfile.GetLength() + 1);
|
||||
}
|
||||
|
||||
{ // metadata section header
|
||||
symtbl_metasec = symbol_table.GetCount() / COFF_IMAGE_SIZEOF_SYMBOL;
|
||||
COFF_IMAGE_SYMBOL msecsym;
|
||||
Zero(msecsym);
|
||||
msecsym.SectionNumber = 1;
|
||||
msecsym.StorageClass = COFF_IMAGE_SYM_CLASS_STATIC;
|
||||
msecsym.NumberOfAuxSymbols = 1;
|
||||
aux_metadata_scn = AddSymbol(msecsym, metadata_secn);
|
||||
}
|
||||
|
||||
{ // data section header
|
||||
symtbl_datasec = symbol_table.GetCount() / COFF_IMAGE_SIZEOF_SYMBOL;
|
||||
COFF_IMAGE_SYMBOL dsecsym;
|
||||
Zero(dsecsym);
|
||||
dsecsym.SectionNumber = 2;
|
||||
dsecsym.StorageClass = COFF_IMAGE_SYM_CLASS_STATIC;
|
||||
dsecsym.NumberOfAuxSymbols = 1;
|
||||
aux_data_scn = AddSymbol(dsecsym, data_secn);
|
||||
}
|
||||
}
|
||||
|
||||
void BinObj::FixAuxSymbols(int data_size)
|
||||
{
|
||||
{ // metadata section info symbol
|
||||
COFF_IMAGE_AUX_SYMBOL msecaux;
|
||||
Zero(msecaux);
|
||||
msecaux.Section.Length = metadata.GetCount();
|
||||
msecaux.Section.NumberOfRelocations = int(relocations.GetCount() / sizeof(COFF_IMAGE_RELOCATION));
|
||||
msecaux.Section.Number = SCN_METADATA;
|
||||
memcpy(symbol_table.GetIter(aux_metadata_scn), &msecaux, COFF_IMAGE_SIZEOF_SYMBOL);
|
||||
}
|
||||
|
||||
{ // data section info symbol
|
||||
COFF_IMAGE_AUX_SYMBOL dsecaux;
|
||||
Zero(dsecaux);
|
||||
dsecaux.Section.Length = data_size;
|
||||
dsecaux.Section.Number = SCN_DATA;
|
||||
memcpy(symbol_table.GetIter(aux_data_scn), &dsecaux, COFF_IMAGE_SIZEOF_SYMBOL);
|
||||
}
|
||||
|
||||
Poke32le(symbol_table_strtbl.Begin(), symbol_table_strtbl.GetCount());
|
||||
}
|
||||
|
||||
void BinObj::WriteFile(String objectfile)
|
||||
{
|
||||
FileOut fo;
|
||||
if(!fo.Open(objectfile))
|
||||
throw Exc(NFormat("error creating file '%s'", objectfile));
|
||||
|
||||
int section_map_offset = sizeof(COFF_IMAGE_FILE_HEADER);
|
||||
int symtbl_offset = section_map_offset + 2 * sizeof(COFF_IMAGE_SECTION_HEADER);
|
||||
int strtbl_offset = symtbl_offset + symbol_table.GetCount();
|
||||
int reloc_offset = strtbl_offset + symbol_table_strtbl.GetCount();
|
||||
int sec1_offset = reloc_offset + relocations.GetCount();
|
||||
int sec2_offset = sec1_offset + metadata.GetCount();
|
||||
|
||||
fo.Put('\0', sec2_offset);
|
||||
|
||||
int data_size = 0;
|
||||
|
||||
{ // data section
|
||||
ASSERT(fo.GetPos() == sec2_offset);
|
||||
for(int i = 0; i < blocks.GetCount(); i++) {
|
||||
const ArrayMap<int, Block>& belem = blocks[i];
|
||||
for(int a = 0; a < belem.GetCount(); a++) {
|
||||
const Block& b = belem[a];
|
||||
String data = LoadFile(b.file);
|
||||
if(data.IsVoid())
|
||||
throw Exc(NFormat("error reading file '%s'", b.file));
|
||||
if(data.GetLength() != b.length)
|
||||
throw Exc(NFormat("length of file '%s' changed (%d -> %d) during object creation",
|
||||
b.file, b.length, data.GetLength()));
|
||||
switch(b.encoding) {
|
||||
case Block::ENC_ZIP: data = ZCompress(data); break;
|
||||
case Block::ENC_BZ2: data = BZ2Compress(data); break;
|
||||
}
|
||||
int offset = (int)fo.GetPos() - sec2_offset;
|
||||
fo.Put(data, data.GetLength());
|
||||
int align = Align(data.GetLength() + 1);
|
||||
fo.Put('\0', align - data.GetLength());
|
||||
ASSERT(b.len_meta_offset >= 0);
|
||||
Poke32le(&metadata[b.len_meta_offset], data.GetLength());
|
||||
Poke32le(&metadata[b.off_meta_offset], offset);
|
||||
data_size += align;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fo.Seek(0);
|
||||
|
||||
FixAuxSymbols(data_size);
|
||||
|
||||
{ // file header
|
||||
ASSERT(fo.GetPos() == 0);
|
||||
COFF_IMAGE_FILE_HEADER hdr;
|
||||
Zero(hdr);
|
||||
hdr.Machine = COFF_IMAGE_FILE_MACHINE_I386;
|
||||
hdr.NumberOfSections = 2;
|
||||
hdr.TimeDateStamp = (dword)time(NULL);
|
||||
hdr.PointerToSymbolTable = symtbl_offset;
|
||||
hdr.NumberOfSymbols = symbol_table.GetCount() / COFF_IMAGE_SIZEOF_SYMBOL;
|
||||
hdr.Characteristics = COFF_IMAGE_FILE_LINE_NUMS_STRIPPED
|
||||
| COFF_IMAGE_FILE_LOCAL_SYMS_STRIPPED
|
||||
| COFF_IMAGE_FILE_BYTES_REVERSED_LO
|
||||
| COFF_IMAGE_FILE_32BIT_MACHINE;
|
||||
fo.Put(&hdr, sizeof(COFF_IMAGE_FILE_HEADER));
|
||||
}
|
||||
|
||||
{ // section map
|
||||
ASSERT(fo.GetPos() == section_map_offset);
|
||||
COFF_IMAGE_SECTION_HEADER meta;
|
||||
Zero(meta);
|
||||
strncpy((char *)meta.Name, metadata_secn, 8);
|
||||
meta.PointerToRawData = sec1_offset;
|
||||
meta.SizeOfRawData = metadata.GetCount();
|
||||
meta.PointerToRelocations = (relocations.IsEmpty() ? 0 : reloc_offset);
|
||||
meta.NumberOfRelocations = int(relocations.GetCount() / sizeof(COFF_IMAGE_RELOCATION));
|
||||
meta.Characteristics = COFF_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
| COFF_IMAGE_SCN_ALIGN_4BYTES
|
||||
| COFF_IMAGE_SCN_MEM_READ | COFF_IMAGE_SCN_MEM_WRITE;
|
||||
fo.Put(&meta, sizeof(COFF_IMAGE_SECTION_HEADER));
|
||||
|
||||
COFF_IMAGE_SECTION_HEADER data;
|
||||
Zero(data);
|
||||
strncpy((char *)data.Name, data_secn, 8);
|
||||
data.PointerToRawData = sec2_offset;
|
||||
data.SizeOfRawData = data_size;
|
||||
data.Characteristics = COFF_IMAGE_SCN_CNT_INITIALIZED_DATA
|
||||
| COFF_IMAGE_SCN_ALIGN_4BYTES
|
||||
| COFF_IMAGE_SCN_MEM_READ | COFF_IMAGE_SCN_MEM_WRITE;
|
||||
fo.Put(&data, sizeof(COFF_IMAGE_SECTION_HEADER));
|
||||
}
|
||||
|
||||
{ // symbol table
|
||||
ASSERT(fo.GetPos() == symtbl_offset);
|
||||
fo.Put(symbol_table.Begin(), symbol_table.GetCount());
|
||||
ASSERT(fo.GetPos() == strtbl_offset);
|
||||
fo.Put(symbol_table_strtbl.Begin(), symbol_table_strtbl.GetCount());
|
||||
}
|
||||
|
||||
{ // relocations
|
||||
ASSERT(fo.GetPos() == reloc_offset);
|
||||
fo.Put(relocations.Begin(), relocations.GetCount());
|
||||
}
|
||||
|
||||
{ // metadata section
|
||||
ASSERT(fo.GetPos() == sec1_offset);
|
||||
fo.Put(metadata.Begin(), metadata.GetCount());
|
||||
}
|
||||
|
||||
fo.Close();
|
||||
if(fo.IsError())
|
||||
throw Exc(NFormat("error writing file '%s'", objectfile));
|
||||
}
|
||||
|
||||
int BinObj::AddMetaData(int value, int reloc_symbol)
|
||||
{
|
||||
int len = metadata.GetCount();
|
||||
metadata.SetCountR(len + 4);
|
||||
Poke32le(metadata.GetIter(len), value);
|
||||
if(reloc_symbol >= 0) {
|
||||
COFF_IMAGE_RELOCATION reloc;
|
||||
reloc.VirtualAddress = len;
|
||||
reloc.SymbolTableIndex = reloc_symbol;
|
||||
reloc.Type = COFF_IMAGE_REL_I386_DIR32;
|
||||
int off = relocations.GetCount();
|
||||
relocations.InsertN(off, sizeof(COFF_IMAGE_RELOCATION));
|
||||
memcpy(relocations.GetIter(off), &reloc, sizeof(COFF_IMAGE_RELOCATION));
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int BinObj::AddSymbol(COFF_IMAGE_SYMBOL& sym, const char *name)
|
||||
{
|
||||
sym.N.Name.Short = sym.N.Name.Long = 0;
|
||||
int nl = (int)strlen(name);
|
||||
if(nl <= 8)
|
||||
memcpy(sym.N.ShortName, name, nl);
|
||||
else {
|
||||
int symlen = symbol_table_strtbl.GetCount();
|
||||
sym.N.Name.Long = symlen;
|
||||
symbol_table_strtbl.InsertN(symlen, nl + 1);
|
||||
memcpy(symbol_table_strtbl.GetIter(symlen), name, nl + 1);
|
||||
}
|
||||
int len = symbol_table.GetCount();
|
||||
symbol_table.InsertN(len, COFF_IMAGE_SIZEOF_SYMBOL * (1 + sym.NumberOfAuxSymbols));
|
||||
memcpy(symbol_table.GetIter(len), &sym, COFF_IMAGE_SIZEOF_SYMBOL);
|
||||
return (sym.NumberOfAuxSymbols ? len + COFF_IMAGE_SIZEOF_SYMBOL : -1);
|
||||
}
|
||||
|
||||
void BinaryToObject(String objectfile, CParser& binscript, String base_dir, Callback1<String> WhenConsole)
|
||||
{
|
||||
BinObj(WhenConsole).Run(objectfile, binscript, base_dir);
|
||||
}
|
||||
|
||||
#ifdef flagMAIN
|
||||
|
||||
#define BINOBJ_VERSION "1.0.r1"
|
||||
#define BINOBJ_DATE Date(2004, 10, 2)
|
||||
#define BINOBJ_COPYRIGHT "Copyright (c) 2004 Tomas Rylek"
|
||||
|
||||
static String Usage()
|
||||
{
|
||||
String out;
|
||||
out <<
|
||||
"BINOBJ: binary to object converter\n"
|
||||
"Version: " BINOBJ_VERSION "\n"
|
||||
"Release date: " << BINOBJ_DATE << "\n"
|
||||
BINOBJ_COPYRIGHT "\n"
|
||||
"\n"
|
||||
"Usage: binobj <definition file> [<output object file>]\n"
|
||||
"\n"
|
||||
"Binary definition file syntax:\n"
|
||||
"BINARY(ident, \"abc.def\") // expose file abc.def as identifier ident\n"
|
||||
"BINARY_ARRAY(array, 0, \"abc.def\") // expose file abc.def as array[0]\n"
|
||||
"\n"
|
||||
"Interfacing declarations:\n"
|
||||
"\n"
|
||||
"extern const unsigned char ident[];\n"
|
||||
"extern const int ident_length;\n"
|
||||
"extern const unsigned char *array[];\n"
|
||||
"extern const int array_length[];\n"
|
||||
"extern const int array_count;\n"
|
||||
;
|
||||
return out;
|
||||
}
|
||||
|
||||
static void TryMain()
|
||||
{
|
||||
const Vector<String>& cmdline = CommandLine();
|
||||
String binfile, outfile;
|
||||
for(int i = 0; i < cmdline.GetCount(); i++) {
|
||||
String arg = cmdline[i];
|
||||
if(IsNull(binfile))
|
||||
binfile = AppendExt(arg, ".bin");
|
||||
else if(IsNull(outfile))
|
||||
outfile = AppendExt(arg, ".obj");
|
||||
else
|
||||
throw Exc(NFormat("no use for argument '%s'", arg));
|
||||
}
|
||||
if(IsNull(binfile)) {
|
||||
puts(Usage());
|
||||
SetExitCode(-1);
|
||||
return;
|
||||
}
|
||||
if(IsNull(outfile))
|
||||
outfile = ForceExt(binfile, ".obj");
|
||||
String bindata = LoadFile(binfile);
|
||||
if(bindata.IsVoid())
|
||||
throw Exc(NFormat("error reading file '%s'", binfile));
|
||||
CParser parser(bindata, binfile);
|
||||
BinaryToObject(outfile, parser, GetFileDirectory(binfile));
|
||||
}
|
||||
|
||||
CONSOLE_APP_MAIN
|
||||
{
|
||||
try {
|
||||
TryMain();
|
||||
}
|
||||
catch(Exc e) {
|
||||
puts("BINOBJ: " + e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
47
uppsrc2/coff/binobj/binobj.h
Normal file
47
uppsrc2/coff/binobj/binobj.h
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef _coff_binobj_binobj_h_
|
||||
#define _coff_binobj_binobj_h_
|
||||
|
||||
#include <coff/coff.h>
|
||||
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
class BinObjInfo {
|
||||
public:
|
||||
BinObjInfo();
|
||||
|
||||
void Parse(CParser& binscript, String base_dir);
|
||||
|
||||
struct Block {
|
||||
Block() : index(-1), length(0), scriptline(-1), encoding(ENC_PLAIN), flags(0), offset(-1), len_meta_offset(-1) {}
|
||||
|
||||
String ident;
|
||||
int index;
|
||||
String file;
|
||||
int length;
|
||||
int scriptline;
|
||||
int encoding;
|
||||
enum {
|
||||
ENC_PLAIN,
|
||||
ENC_ZIP,
|
||||
ENC_BZ2,
|
||||
};
|
||||
int flags;
|
||||
enum {
|
||||
FLG_ARRAY = 0x01,
|
||||
FLG_MASK = 0x02,
|
||||
};
|
||||
|
||||
int offset;
|
||||
int off_meta_offset;
|
||||
int len_meta_offset;
|
||||
};
|
||||
|
||||
VectorMap< String, ArrayMap<int, Block> > blocks;
|
||||
};
|
||||
|
||||
void BinaryToObject(String objectfile, CParser& binscript, String base_dir, Callback1<String> WhenConsole);
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
14
uppsrc2/coff/binobj/binobj.upp
Normal file
14
uppsrc2/coff/binobj/binobj.upp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
description "Converts binary data to COFF object files\377";
|
||||
|
||||
optimize_speed;
|
||||
|
||||
uses
|
||||
coff,
|
||||
plugin\bz2;
|
||||
|
||||
file
|
||||
binobj.h,
|
||||
binobj.cpp,
|
||||
Info readonly separator,
|
||||
Copying;
|
||||
|
||||
5
uppsrc2/coff/binobj/init
Normal file
5
uppsrc2/coff/binobj/init
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
#ifndef _coff_binobj_icpp_init_stub
|
||||
#define _coff_binobj_icpp_init_stub
|
||||
#include "coff/init"
|
||||
#include "plugin\bz2/init"
|
||||
#endif
|
||||
6
uppsrc2/coff/coff.cpp
Normal file
6
uppsrc2/coff/coff.cpp
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
#include "coff.h"
|
||||
|
||||
void Main()
|
||||
{
|
||||
|
||||
}
|
||||
22
uppsrc2/coff/coff.h
Normal file
22
uppsrc2/coff/coff.h
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
#ifndef _coff_coff_h
|
||||
#define _coff_coff_h
|
||||
|
||||
#include <Core/Core.h>
|
||||
#include <time.h>
|
||||
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#include "defs.h"
|
||||
#include "util.h"
|
||||
#include "lib.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#define PATH_HAS_CASE 0
|
||||
#else
|
||||
#define PATH_HAS_CASE 1
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
19
uppsrc2/coff/coff.upp
Normal file
19
uppsrc2/coff/coff.upp
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
description "Library for handling with COFF object file format (used by GCC toolchain)\377";
|
||||
|
||||
optimize_speed;
|
||||
|
||||
uses
|
||||
Core;
|
||||
|
||||
file
|
||||
coff.h,
|
||||
defs.h,
|
||||
defs.cpp,
|
||||
stab.def,
|
||||
util.h,
|
||||
util.cpp,
|
||||
lib.h,
|
||||
lib.cpp,
|
||||
Info readonly separator,
|
||||
Copying;
|
||||
|
||||
70
uppsrc2/coff/defs.cpp
Normal file
70
uppsrc2/coff/defs.cpp
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
#include "coff.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
|
||||
#define MACHINE(mach) { ASSTRING(mach), COMBINE(COFF_IMAGE_FILE_MACHINE_, mach) },
|
||||
|
||||
static const MachineInfo _COFFMachineList[] =
|
||||
{
|
||||
MACHINE(I386)
|
||||
MACHINE(R3000)
|
||||
MACHINE(R4000)
|
||||
MACHINE(R10000)
|
||||
MACHINE(WCEMIPSV2)
|
||||
MACHINE(ALPHA)
|
||||
MACHINE(POWERPC)
|
||||
MACHINE(SH3)
|
||||
MACHINE(SH3E)
|
||||
MACHINE(SH4)
|
||||
MACHINE(ARM)
|
||||
MACHINE(THUMB)
|
||||
MACHINE(IA64)
|
||||
MACHINE(MIPS16)
|
||||
MACHINE(MIPSFPU)
|
||||
MACHINE(MIPSFPU16)
|
||||
MACHINE(ALPHA64)
|
||||
MACHINE(AXP64)
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
const MachineInfo *COFFMachineList() { return _COFFMachineList; }
|
||||
|
||||
String COFFMachineNames()
|
||||
{
|
||||
String out;
|
||||
for(const MachineInfo *mlist = COFFMachineList(), *mi = mlist; mi->name; mi++)
|
||||
out << (mi == mlist ? "" : ", ") << mi->name;
|
||||
return out;
|
||||
}
|
||||
|
||||
String COFFMachineName(int code)
|
||||
{
|
||||
for(const MachineInfo *mi = COFFMachineList(); mi->name; mi++)
|
||||
if(mi->code == code)
|
||||
return mi->name;
|
||||
return NFormat("UNKNOWN(%04x)", code);
|
||||
}
|
||||
|
||||
int COFFMachineCode(String name)
|
||||
{
|
||||
for(const MachineInfo *mi = COFFMachineList(); mi->name; mi++)
|
||||
if(mi->name == name)
|
||||
return mi->code;
|
||||
return COFF_IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
}
|
||||
|
||||
String COFFSymbolName(const COFF_IMAGE_SYMBOL& sym, const char *strtbl)
|
||||
{
|
||||
String name;
|
||||
if(sym.N.Name.Short)
|
||||
name = MaxLenString(sym.N.ShortName, 8);
|
||||
else
|
||||
name = strtbl + sym.N.Name.Long;
|
||||
return name;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
781
uppsrc2/coff/defs.h
Normal file
781
uppsrc2/coff/defs.h
Normal file
|
|
@ -0,0 +1,781 @@
|
|||
#ifndef _console_coff_defs_h_
|
||||
#define _console_coff_defs_h_
|
||||
|
||||
// compatibility COFF headers
|
||||
|
||||
#ifdef COMPILER_MSC
|
||||
#pragma pack(push, 1)
|
||||
#endif
|
||||
|
||||
const int COFF_IMAGE_ARCHIVE_START_SIZE = 8;
|
||||
#define COFF_IMAGE_ARCHIVE_START "!<arch>\n"
|
||||
const char COFF_IMAGE_ARCHIVE_PAD = '\n';
|
||||
const char COFF_IMAGE_ARCHIVE_END1 = '`';
|
||||
const char COFF_IMAGE_ARCHIVE_END2 = '\n';
|
||||
|
||||
const int COFF_IMAGE_FILE_RELOCS_STRIPPED = 0x0001; // Relocation info stripped from file.
|
||||
const int COFF_IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002; // File is executable (i.e. no unresolved externel references).
|
||||
const int COFF_IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004; // Line nunbers stripped from file.
|
||||
const int COFF_IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008; // Local symbols stripped from file.
|
||||
const int COFF_IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010; // Agressively trim working set
|
||||
const int COFF_IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020; // App can handle >2gb addresses
|
||||
const int COFF_IMAGE_FILE_BYTES_REVERSED_LO = 0x0080; // Bytes of machine word are reversed.
|
||||
const int COFF_IMAGE_FILE_32BIT_MACHINE = 0x0100; // 32 bit word machine.
|
||||
const int COFF_IMAGE_FILE_DEBUG_STRIPPED = 0x0200; // Debugging info stripped from file in .DBG file
|
||||
const int COFF_IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400; // If Image is on removable media, copy and run from the swap file.
|
||||
const int COFF_IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800; // If Image is on Net, copy and run from the swap file.
|
||||
const int COFF_IMAGE_FILE_SYSTEM = 0x1000; // System File.
|
||||
const int COFF_IMAGE_FILE_DLL = 0x2000; // File is a DLL.
|
||||
const int COFF_IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000; // File should only be run on a UP machine
|
||||
const int COFF_IMAGE_FILE_BYTES_REVERSED_HI = 0x8000; // Bytes of machine word are reversed.
|
||||
|
||||
const int COFF_IMAGE_FILE_MACHINE_UNKNOWN = 0;
|
||||
const int COFF_IMAGE_FILE_MACHINE_I386 = 0x014c; // Intel 386.
|
||||
const int COFF_IMAGE_FILE_MACHINE_R3000 = 0x0162; // MIPS little-endian; 0x160 big-endian
|
||||
const int COFF_IMAGE_FILE_MACHINE_R4000 = 0x0166; // MIPS little-endian
|
||||
const int COFF_IMAGE_FILE_MACHINE_R10000 = 0x0168; // MIPS little-endian
|
||||
const int COFF_IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169; // MIPS little-endian WCE v2
|
||||
const int COFF_IMAGE_FILE_MACHINE_ALPHA = 0x0184; // Alpha_AXP
|
||||
const int COFF_IMAGE_FILE_MACHINE_POWERPC = 0x01F0; // IBM PowerPC Little-Endian
|
||||
const int COFF_IMAGE_FILE_MACHINE_SH3 = 0x01a2; // SH3 little-endian
|
||||
const int COFF_IMAGE_FILE_MACHINE_SH3E = 0x01a4; // SH3E little-endian
|
||||
const int COFF_IMAGE_FILE_MACHINE_SH4 = 0x01a6; // SH4 little-endian
|
||||
const int COFF_IMAGE_FILE_MACHINE_ARM = 0x01c0; // ARM Little-Endian
|
||||
const int COFF_IMAGE_FILE_MACHINE_THUMB = 0x01c2;
|
||||
const int COFF_IMAGE_FILE_MACHINE_IA64 = 0x0200; // Intel 64
|
||||
const int COFF_IMAGE_FILE_MACHINE_MIPS16 = 0x0266; // MIPS
|
||||
const int COFF_IMAGE_FILE_MACHINE_MIPSFPU = 0x0366; // MIPS
|
||||
const int COFF_IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466; // MIPS
|
||||
const int COFF_IMAGE_FILE_MACHINE_ALPHA64 = 0x0284; // ALPHA64
|
||||
const int COFF_IMAGE_FILE_MACHINE_AXP64 = COFF_IMAGE_FILE_MACHINE_ALPHA64;
|
||||
|
||||
struct MachineInfo
|
||||
{
|
||||
const char *name;
|
||||
int code;
|
||||
};
|
||||
|
||||
const MachineInfo *COFFMachineList();
|
||||
String COFFMachineNames();
|
||||
String COFFMachineName(int code);
|
||||
int COFFMachineCode(String name);
|
||||
|
||||
struct COFF_IMAGE_SYMBOL
|
||||
{
|
||||
union {
|
||||
byte ShortName[8];
|
||||
struct {
|
||||
dword Short; // if 0, use LongName
|
||||
dword Long; // offset into string table
|
||||
} Name;
|
||||
byte *LongName[2];
|
||||
} N;
|
||||
dword Value;
|
||||
short SectionNumber;
|
||||
word Type;
|
||||
byte StorageClass;
|
||||
byte NumberOfAuxSymbols;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
struct COFF_IMAGE_FILE_HEADER
|
||||
{
|
||||
word Machine;
|
||||
word NumberOfSections;
|
||||
dword TimeDateStamp;
|
||||
dword PointerToSymbolTable;
|
||||
dword NumberOfSymbols;
|
||||
word SizeOfOptionalHeader;
|
||||
word Characteristics;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
const int COFF_IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
|
||||
|
||||
struct COFF_IMAGE_DATA_DIRECTORY
|
||||
{
|
||||
dword VirtualAddress;
|
||||
dword Size;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
struct COFF_IMAGE_OPTIONAL_HEADER32
|
||||
{
|
||||
//
|
||||
// Standard fields.
|
||||
//
|
||||
|
||||
word Magic;
|
||||
byte MajorLinkerVersion;
|
||||
byte MinorLinkerVersion;
|
||||
dword SizeOfCode;
|
||||
dword SizeOfInitializedData;
|
||||
dword SizeOfUninitializedData;
|
||||
dword AddressOfEntryPoint;
|
||||
dword BaseOfCode;
|
||||
dword BaseOfData;
|
||||
|
||||
//
|
||||
// NT additional fields.
|
||||
//
|
||||
|
||||
dword ImageBase;
|
||||
dword SectionAlignment;
|
||||
dword FileAlignment;
|
||||
word MajorOperatingSystemVersion;
|
||||
word MinorOperatingSystemVersion;
|
||||
word MajorImageVersion;
|
||||
word MinorImageVersion;
|
||||
word MajorSubsystemVersion;
|
||||
word MinorSubsystemVersion;
|
||||
dword Win32VersionValue;
|
||||
dword SizeOfImage;
|
||||
dword SizeOfHeaders;
|
||||
dword CheckSum;
|
||||
word Subsystem;
|
||||
word DllCharacteristics;
|
||||
dword SizeOfStackReserve;
|
||||
dword SizeOfStackCommit;
|
||||
dword SizeOfHeapReserve;
|
||||
dword SizeOfHeapCommit;
|
||||
dword LoaderFlags;
|
||||
dword NumberOfRvaAndSizes;
|
||||
COFF_IMAGE_DATA_DIRECTORY DataDirectory[COFF_IMAGE_NUMBEROF_DIRECTORY_ENTRIES];
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
struct COFF_IMPORT_OBJECT_HEADER
|
||||
{
|
||||
word Sig1; // Must be IMAGE_FILE_MACHINE_UNKNOWN
|
||||
word Sig2; // Must be IMPORT_OBJECT_HDR_SIG2.
|
||||
word Version;
|
||||
word Machine;
|
||||
dword TimeDateStamp; // Time/date stamp
|
||||
dword SizeOfData; // particularly useful for incremental links
|
||||
|
||||
union {
|
||||
word Ordinal; // if grf & IMPORT_OBJECT_ORDINAL
|
||||
word Hint;
|
||||
};
|
||||
|
||||
word Type : 2; // IMPORT_TYPE
|
||||
word NameType : 3; // IMPORT_NAME_TYPE
|
||||
word Reserved : 11; // Reserved. Must be zero.
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
enum COFF_IMPORT_TYPE
|
||||
{
|
||||
COFF_IMPORT_CODE = 0,
|
||||
COFF_IMPORT_DATA = 1,
|
||||
COFF_IMPORT_CONST = 2,
|
||||
};
|
||||
|
||||
enum COFF_IMPORT_OBJECT_NAME_TYPE
|
||||
{
|
||||
COFF_IMPORT_OBJECT_ORDINAL = 0, // Import by ordinal
|
||||
COFF_IMPORT_OBJECT_NAME = 1, // Import name == public symbol name.
|
||||
COFF_IMPORT_OBJECT_NAME_NO_PREFIX = 2, // Import name == public symbol name skipping leading ?, @, or optionally _.
|
||||
COFF_IMPORT_OBJECT_NAME_UNDECORATE = 3, // Import name == public symbol name skipping leading ?, @, or optionally _
|
||||
// and truncating at first @
|
||||
};
|
||||
|
||||
struct COFF_IMAGE_EXPORT_DIRECTORY_TABLE
|
||||
{
|
||||
dword ExportFlags;
|
||||
dword DateTimeStamp;
|
||||
word MajorVersion;
|
||||
word MinorVersion;
|
||||
dword NameRVA;
|
||||
dword OrdinalBase;
|
||||
dword AddressTableEntries;
|
||||
dword NumberOfNamePointers;
|
||||
dword ExportAddressTableRVA;
|
||||
dword NamePointerTableRVA;
|
||||
dword OrdinalTableRVA;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
const size_t COFF_IMAGE_SIZEOF_SHORT_NAME = 8;
|
||||
|
||||
struct COFF_IMAGE_SECTION_HEADER
|
||||
{
|
||||
byte Name[COFF_IMAGE_SIZEOF_SHORT_NAME];
|
||||
union {
|
||||
dword PhysicalAddress;
|
||||
dword VirtualSize;
|
||||
} Misc;
|
||||
dword VirtualAddress;
|
||||
dword SizeOfRawData;
|
||||
dword PointerToRawData;
|
||||
dword PointerToRelocations;
|
||||
dword PointerToLinenumbers;
|
||||
word NumberOfRelocations;
|
||||
word NumberOfLinenumbers;
|
||||
dword Characteristics;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
const dword COFF_IMAGE_SCN_TYPE_REG = 0x00000000; // Reserved.
|
||||
const dword COFF_IMAGE_SCN_TYPE_DSECT = 0x00000001; // Reserved.
|
||||
const dword COFF_IMAGE_SCN_TYPE_NOLOAD = 0x00000002; // Reserved.
|
||||
const dword COFF_IMAGE_SCN_TYPE_GROUP = 0x00000004; // Reserved.
|
||||
const dword COFF_IMAGE_SCN_TYPE_NO_PAD = 0x00000008; // Reserved.
|
||||
const dword COFF_IMAGE_SCN_TYPE_COPY = 0x00000010; // Reserved.
|
||||
|
||||
const dword COFF_IMAGE_SCN_CNT_CODE = 0x00000020; // Section contains code.
|
||||
const dword COFF_IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040; // Section contains initialized data.
|
||||
const dword COFF_IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080; // Section contains uninitialized data.
|
||||
|
||||
const dword COFF_IMAGE_SCN_LNK_OTHER = 0x00000100; // Reserved.
|
||||
const dword COFF_IMAGE_SCN_LNK_INFO = 0x00000200; // Section contains comments or some other type of information.
|
||||
const dword COFF_IMAGE_SCN_TYPE_OVER = 0x00000400; // Reserved.
|
||||
const dword COFF_IMAGE_SCN_LNK_REMOVE = 0x00000800; // Section contents will not become part of image.
|
||||
const dword COFF_IMAGE_SCN_LNK_COMDAT = 0x00001000; // Section contents comdat.
|
||||
// = 0x00002000; // Reserved.
|
||||
//const dword COFF_IMAGE_SCN_MEM_PROTECTED - Obsolete= 0x00004000
|
||||
const dword COFF_IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000; // Reset speculative exceptions handling bits in the TLB entries for this section.
|
||||
const dword COFF_IMAGE_SCN_GPREL = 0x00008000; // Section content can be accessed relative to GP
|
||||
const dword COFF_IMAGE_SCN_MEM_FARDATA = 0x00008000;
|
||||
//const dword COFF_IMAGE_SCN_MEM_SYSHEAP - Obsolete = 0x00010000
|
||||
const dword COFF_IMAGE_SCN_MEM_PURGEABLE = 0x00020000;
|
||||
const dword COFF_IMAGE_SCN_MEM_16BIT = 0x00020000;
|
||||
const dword COFF_IMAGE_SCN_MEM_LOCKED = 0x00040000;
|
||||
const dword COFF_IMAGE_SCN_MEM_PRELOAD = 0x00080000;
|
||||
|
||||
const dword COFF_IMAGE_SCN_ALIGN_1BYTES = 0x00100000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_2BYTES = 0x00200000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_4BYTES = 0x00300000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_8BYTES = 0x00400000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_16BYTES = 0x00500000; // Default alignment if no others are specified.
|
||||
const dword COFF_IMAGE_SCN_ALIGN_32BYTES = 0x00600000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_64BYTES = 0x00700000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_128BYTES = 0x00800000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_256BYTES = 0x00900000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_512BYTES = 0x00A00000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000; //
|
||||
const dword COFF_IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000; //
|
||||
|
||||
const dword COFF_IMAGE_SCN_ALIGN_MASK = 0x00F00000;
|
||||
|
||||
// Unused = 0x00F00000;
|
||||
|
||||
const dword COFF_IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000; // Section contains extended relocations.
|
||||
const dword COFF_IMAGE_SCN_MEM_DISCARDABLE = 0x02000000; // Section can be discarded.
|
||||
const dword COFF_IMAGE_SCN_MEM_NOT_CACHED = 0x04000000; // Section is not cachable.
|
||||
const dword COFF_IMAGE_SCN_MEM_NOT_PAGED = 0x08000000; // Section is not pageable.
|
||||
const dword COFF_IMAGE_SCN_MEM_SHARED = 0x10000000; // Section is shareable.
|
||||
const dword COFF_IMAGE_SCN_MEM_EXECUTE = 0x20000000; // Section is executable.
|
||||
const dword COFF_IMAGE_SCN_MEM_READ = 0x40000000; // Section is readable.
|
||||
const dword COFF_IMAGE_SCN_MEM_WRITE = 0x80000000; // Section is writeable.
|
||||
|
||||
const int COFF_IMAGE_SYM_TYPE_NULL = 0x0000; // no type.
|
||||
const int COFF_IMAGE_SYM_TYPE_VOID = 0x0001; //
|
||||
const int COFF_IMAGE_SYM_TYPE_CHAR = 0x0002; // type character.
|
||||
const int COFF_IMAGE_SYM_TYPE_SHORT = 0x0003; // type short integer.
|
||||
const int COFF_IMAGE_SYM_TYPE_INT = 0x0004; //
|
||||
const int COFF_IMAGE_SYM_TYPE_LONG = 0x0005; //
|
||||
const int COFF_IMAGE_SYM_TYPE_FLOAT = 0x0006; //
|
||||
const int COFF_IMAGE_SYM_TYPE_DOUBLE = 0x0007; //
|
||||
const int COFF_IMAGE_SYM_TYPE_STRUCT = 0x0008; //
|
||||
const int COFF_IMAGE_SYM_TYPE_UNION = 0x0009; //
|
||||
const int COFF_IMAGE_SYM_TYPE_ENUM = 0x000A; // enumeration.
|
||||
const int COFF_IMAGE_SYM_TYPE_MOE = 0x000B; // member of enumeration.
|
||||
const int COFF_IMAGE_SYM_TYPE_BYTE = 0x000C; //
|
||||
const int COFF_IMAGE_SYM_TYPE_WORD = 0x000D; //
|
||||
const int COFF_IMAGE_SYM_TYPE_UINT = 0x000E; //
|
||||
const int COFF_IMAGE_SYM_TYPE_DWORD = 0x000F; //
|
||||
const int COFF_IMAGE_SYM_TYPE_PCODE = 0x8000; //
|
||||
//
|
||||
// Type (derived) values.
|
||||
//
|
||||
|
||||
const int COFF_IMAGE_SYM_DTYPE_NULL = 0; // no derived type.
|
||||
const int COFF_IMAGE_SYM_DTYPE_POINTER = 1; // pointer.
|
||||
const int COFF_IMAGE_SYM_DTYPE_FUNCTION = 2; // function.
|
||||
const int COFF_IMAGE_SYM_DTYPE_ARRAY = 3; // array.
|
||||
|
||||
//
|
||||
// TLS Chaacteristic Flags
|
||||
//
|
||||
const int COFF_IMAGE_SCN_SCALE_INDEX = 0x00000001; // Tls index is scaled
|
||||
|
||||
const int COFF_IMAGE_SYM_CLASS_END_OF_FUNCTION = (byte )-1;
|
||||
const int COFF_IMAGE_SYM_CLASS_NULL = 0x0000;
|
||||
const int COFF_IMAGE_SYM_CLASS_AUTOMATIC = 0x0001;
|
||||
const int COFF_IMAGE_SYM_CLASS_EXTERNAL = 0x0002;
|
||||
const int COFF_IMAGE_SYM_CLASS_STATIC = 0x0003;
|
||||
const int COFF_IMAGE_SYM_CLASS_REGISTER = 0x0004;
|
||||
const int COFF_IMAGE_SYM_CLASS_EXTERNAL_DEF = 0x0005;
|
||||
const int COFF_IMAGE_SYM_CLASS_LABEL = 0x0006;
|
||||
const int COFF_IMAGE_SYM_CLASS_UNDEFINED_LABEL = 0x0007;
|
||||
const int COFF_IMAGE_SYM_CLASS_MEMBER_OF_STRUCT = 0x0008;
|
||||
const int COFF_IMAGE_SYM_CLASS_ARGUMENT = 0x0009;
|
||||
const int COFF_IMAGE_SYM_CLASS_STRUCT_TAG = 0x000A;
|
||||
const int COFF_IMAGE_SYM_CLASS_MEMBER_OF_UNION = 0x000B;
|
||||
const int COFF_IMAGE_SYM_CLASS_UNION_TAG = 0x000C;
|
||||
const int COFF_IMAGE_SYM_CLASS_TYPE_DEFINITION = 0x000D;
|
||||
const int COFF_IMAGE_SYM_CLASS_UNDEFINED_STATIC = 0x000E;
|
||||
const int COFF_IMAGE_SYM_CLASS_ENUM_TAG = 0x000F;
|
||||
const int COFF_IMAGE_SYM_CLASS_MEMBER_OF_ENUM = 0x0010;
|
||||
const int COFF_IMAGE_SYM_CLASS_REGISTER_PARAM = 0x0011;
|
||||
const int COFF_IMAGE_SYM_CLASS_BIT_FIELD = 0x0012;
|
||||
|
||||
const int COFF_IMAGE_SYM_CLASS_FAR_EXTERNAL = 0x0044; //
|
||||
|
||||
const int COFF_IMAGE_SYM_CLASS_BLOCK = 0x0064;
|
||||
const int COFF_IMAGE_SYM_CLASS_FUNCTION = 0x0065;
|
||||
const int COFF_IMAGE_SYM_CLASS_END_OF_STRUCT = 0x0066;
|
||||
const int COFF_IMAGE_SYM_CLASS_FILE = 0x0067;
|
||||
// new
|
||||
const int COFF_IMAGE_SYM_CLASS_SECTION = 0x0068;
|
||||
const int COFF_IMAGE_SYM_CLASS_WEAK_EXTERNAL = 0x0069;
|
||||
|
||||
const int COFF_IMAGE_SIZEOF_SYMBOL = 18;
|
||||
|
||||
union COFF_IMAGE_AUX_SYMBOL
|
||||
{
|
||||
struct {
|
||||
dword TagIndex; // struct, union, or enum tag index
|
||||
union {
|
||||
struct {
|
||||
word Linenumber; // declaration line number
|
||||
word Size; // size of struct, union, or enum
|
||||
} LnSz;
|
||||
dword TotalSize;
|
||||
} Misc;
|
||||
union {
|
||||
struct { // if ISFCN, tag, or .bb
|
||||
dword PointerToLinenumber;
|
||||
dword PointerToNextFunction;
|
||||
} Function;
|
||||
struct { // if ISARY, up to 4 dimen.
|
||||
word Dimension[4];
|
||||
} Array_;
|
||||
} FcnAry;
|
||||
word TvIndex; // tv index
|
||||
} Sym;
|
||||
struct {
|
||||
byte Name[COFF_IMAGE_SIZEOF_SYMBOL];
|
||||
} File;
|
||||
struct {
|
||||
dword Length; // section length
|
||||
word NumberOfRelocations; // number of relocation entries
|
||||
word NumberOfLinenumbers; // number of line numbers
|
||||
dword CheckSum; // checksum for communal
|
||||
short Number; // section number to associate with
|
||||
byte Selection; // communal selection type
|
||||
} Section;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
const int COFF_IMAGE_COMDAT_SELECT_NODUPLICATES = 1;
|
||||
const int COFF_IMAGE_COMDAT_SELECT_ANY = 2;
|
||||
const int COFF_IMAGE_COMDAT_SELECT_SAME_SIZE = 3;
|
||||
const int COFF_IMAGE_COMDAT_SELECT_EXACT_MATCH = 4;
|
||||
const int COFF_IMAGE_COMDAT_SELECT_ASSOCIATIVE = 5;
|
||||
const int COFF_IMAGE_COMDAT_SELECT_LARGEST = 6;
|
||||
const int COFF_IMAGE_COMDAT_SELECT_NEWEST = 7;
|
||||
|
||||
struct COFF_IMAGE_RELOCATION : Moveable<COFF_IMAGE_RELOCATION>
|
||||
{
|
||||
union {
|
||||
dword VirtualAddress;
|
||||
dword RelocCount; // Set to the real count when IMAGE_SCN_LNK_NRELOC_OVFL is set
|
||||
};
|
||||
dword SymbolTableIndex;
|
||||
word Type;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
const int COFF_IMAGE_SUBSYSTEM_DEFAULT = -1; // system-specific default (ULD-specific)
|
||||
|
||||
const int COFF_IMAGE_SUBSYSTEM_UNKNOWN = 0; // Unknown subsystem.
|
||||
const int COFF_IMAGE_SUBSYSTEM_NATIVE = 1; // Image doesn't require a subsystem.
|
||||
const int COFF_IMAGE_SUBSYSTEM_WINDOWS_GUI = 2; // Image runs in the Windows GUI subsystem.
|
||||
const int COFF_IMAGE_SUBSYSTEM_WINDOWS_CUI = 3; // Image runs in the Windows character subsystem.
|
||||
const int COFF_IMAGE_SUBSYSTEM_OS2_CUI = 5; // image runs in the OS/2 character subsystem.
|
||||
const int COFF_IMAGE_SUBSYSTEM_POSIX_CUI = 7; // image runs in the Posix character subsystem.
|
||||
const int COFF_IMAGE_SUBSYSTEM_NATIVE_WINDOWS = 8; // image is a native Win9x driver.
|
||||
const int COFF_IMAGE_SUBSYSTEM_WINDOWS_CE_GUI = 9; // Image runs in the Windows CE subsystem.
|
||||
|
||||
struct COFF_IMAGE_ARCHIVE_MEMBER_HEADER
|
||||
{
|
||||
byte Name[16]; // File member name - `/' terminated.
|
||||
byte Date[12]; // File member date - decimal.
|
||||
byte UserID[6]; // File member user id - decimal.
|
||||
byte GroupID[6]; // File member group id - decimal.
|
||||
byte Mode[8]; // File member mode - octal.
|
||||
byte Size[10]; // File member size - decimal.
|
||||
byte EndHeader[2]; // String to end header.
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
struct COFF_IMAGE_IMPORT_DESCRIPTOR
|
||||
{
|
||||
union {
|
||||
dword Characteristics; // 0 for terminating null import descriptor
|
||||
dword OriginalFirstThunk; // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
|
||||
};
|
||||
dword TimeDateStamp; // 0 if not bound,
|
||||
// -1 if bound, and real date\time stamp
|
||||
// in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
|
||||
// O.W. date/time stamp of DLL bound to (Old BIND)
|
||||
|
||||
dword ForwarderChain; // -1 if no forwarders
|
||||
dword Name;
|
||||
dword FirstThunk; // RVA to IAT (if bound this IAT has actual addresses)
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
//
|
||||
// I386 relocation types.
|
||||
//
|
||||
const word COFF_IMAGE_REL_I386_ABSOLUTE = 0x0000; // Reference is absolute, no relocation is necessary
|
||||
const word COFF_IMAGE_REL_I386_DIR16 = 0x0001; // Direct 16-bit reference to the symbols virtual address
|
||||
const word COFF_IMAGE_REL_I386_REL16 = 0x0002; // PC-relative 16-bit reference to the symbols virtual address
|
||||
const word COFF_IMAGE_REL_I386_DIR32 = 0x0006; // Direct 32-bit reference to the symbols virtual address
|
||||
const word COFF_IMAGE_REL_I386_DIR32NB = 0x0007; // Direct 32-bit reference to the symbols virtual address, base not included
|
||||
const word COFF_IMAGE_REL_I386_SEG12 = 0x0009; // Direct 16-bit reference to the segment-selector bits of a 32-bit virtual address
|
||||
const word COFF_IMAGE_REL_I386_SECTION = 0x000A;
|
||||
const word COFF_IMAGE_REL_I386_SECREL = 0x000B;
|
||||
const word COFF_IMAGE_REL_I386_REL32 = 0x0014; // PC-relative 32-bit reference to the symbols virtual address
|
||||
|
||||
//
|
||||
// MIPS relocation types.
|
||||
//
|
||||
|
||||
const word COFF_IMAGE_REL_MIPS_ABSOLUTE = 0x0000; // Reference is absolute, no relocation is necessary
|
||||
const word COFF_IMAGE_REL_MIPS_REFHALF = 0x0001;
|
||||
const word COFF_IMAGE_REL_MIPS_REFWORD = 0x0002;
|
||||
const word COFF_IMAGE_REL_MIPS_JMPADDR = 0x0003;
|
||||
const word COFF_IMAGE_REL_MIPS_REFHI = 0x0004;
|
||||
const word COFF_IMAGE_REL_MIPS_REFLO = 0x0005;
|
||||
const word COFF_IMAGE_REL_MIPS_GPREL = 0x0006;
|
||||
const word COFF_IMAGE_REL_MIPS_LITERAL = 0x0007;
|
||||
const word COFF_IMAGE_REL_MIPS_SECTION = 0x000A;
|
||||
const word COFF_IMAGE_REL_MIPS_SECREL = 0x000B;
|
||||
const word COFF_IMAGE_REL_MIPS_SECRELLO = 0x000C; // Low 16-bit section relative referemce (used for >32k TLS)
|
||||
const word COFF_IMAGE_REL_MIPS_SECRELHI = 0x000D; // High 16-bit section relative reference (used for >32k TLS)
|
||||
const word COFF_IMAGE_REL_MIPS_JMPADDR16 = 0x0010;
|
||||
const word COFF_IMAGE_REL_MIPS_REFWORDNB = 0x0022;
|
||||
const word COFF_IMAGE_REL_MIPS_PAIR = 0x0025;
|
||||
|
||||
//
|
||||
// Alpha Relocation types.
|
||||
//
|
||||
|
||||
const word COFF_IMAGE_REL_ALPHA_ABSOLUTE = 0x0000;
|
||||
const word COFF_IMAGE_REL_ALPHA_REFLONG = 0x0001;
|
||||
const word COFF_IMAGE_REL_ALPHA_REFQUAD = 0x0002;
|
||||
const word COFF_IMAGE_REL_ALPHA_GPREL32 = 0x0003;
|
||||
const word COFF_IMAGE_REL_ALPHA_LITERAL = 0x0004;
|
||||
const word COFF_IMAGE_REL_ALPHA_LITUSE = 0x0005;
|
||||
const word COFF_IMAGE_REL_ALPHA_GPDISP = 0x0006;
|
||||
const word COFF_IMAGE_REL_ALPHA_BRADDR = 0x0007;
|
||||
const word COFF_IMAGE_REL_ALPHA_HINT = 0x0008;
|
||||
const word COFF_IMAGE_REL_ALPHA_INLINE_REFLONG = 0x0009;
|
||||
const word COFF_IMAGE_REL_ALPHA_REFHI = 0x000A;
|
||||
const word COFF_IMAGE_REL_ALPHA_REFLO = 0x000B;
|
||||
const word COFF_IMAGE_REL_ALPHA_PAIR = 0x000C;
|
||||
const word COFF_IMAGE_REL_ALPHA_MATCH = 0x000D;
|
||||
const word COFF_IMAGE_REL_ALPHA_SECTION = 0x000E;
|
||||
const word COFF_IMAGE_REL_ALPHA_SECREL = 0x000F;
|
||||
const word COFF_IMAGE_REL_ALPHA_REFLONGNB = 0x0010;
|
||||
const word COFF_IMAGE_REL_ALPHA_SECRELLO = 0x0011; // Low 16-bit section relative reference
|
||||
const word COFF_IMAGE_REL_ALPHA_SECRELHI = 0x0012; // High 16-bit section relative reference
|
||||
const word COFF_IMAGE_REL_ALPHA_REFQ3 = 0x0013; // High 16 bits of 48 bit reference
|
||||
const word COFF_IMAGE_REL_ALPHA_REFQ2 = 0x0014; // Middle 16 bits of 48 bit reference
|
||||
const word COFF_IMAGE_REL_ALPHA_REFQ1 = 0x0015; // Low 16 bits of 48 bit reference
|
||||
const word COFF_IMAGE_REL_ALPHA_GPRELLO = 0x0016; // Low 16-bit GP relative reference
|
||||
const word COFF_IMAGE_REL_ALPHA_GPRELHI = 0x0017; // High 16-bit GP relative reference
|
||||
|
||||
|
||||
//
|
||||
// IBM PowerPC relocation types.
|
||||
//
|
||||
|
||||
const word COFF_IMAGE_REL_PPC_ABSOLUTE = 0x0000; // NOP
|
||||
const word COFF_IMAGE_REL_PPC_ADDR64 = 0x0001; // 64-bit address
|
||||
const word COFF_IMAGE_REL_PPC_ADDR32 = 0x0002; // 32-bit address
|
||||
const word COFF_IMAGE_REL_PPC_ADDR24 = 0x0003; // 26-bit address, shifted left 2 (branch absolute)
|
||||
const word COFF_IMAGE_REL_PPC_ADDR16 = 0x0004; // 16-bit address
|
||||
const word COFF_IMAGE_REL_PPC_ADDR14 = 0x0005; // 16-bit address, shifted left 2 (load doubleword)
|
||||
const word COFF_IMAGE_REL_PPC_REL24 = 0x0006; // 26-bit PC-relative offset, shifted left 2 (branch relative)
|
||||
const word COFF_IMAGE_REL_PPC_REL14 = 0x0007; // 16-bit PC-relative offset, shifted left 2 (br cond relative)
|
||||
const word COFF_IMAGE_REL_PPC_TOCREL16 = 0x0008; // 16-bit offset from TOC base
|
||||
const word COFF_IMAGE_REL_PPC_TOCREL14 = 0x0009; // 16-bit offset from TOC base, shifted left 2 (load doubleword)
|
||||
|
||||
const word COFF_IMAGE_REL_PPC_ADDR32NB = 0x000A; // 32-bit addr w/o image base
|
||||
const word COFF_IMAGE_REL_PPC_SECREL = 0x000B; // va of containing section (as in an image sectionhdr)
|
||||
const word COFF_IMAGE_REL_PPC_SECTION = 0x000C; // sectionheader number
|
||||
const word COFF_IMAGE_REL_PPC_IFGLUE = 0x000D; // substitute TOC restore instruction iff symbol is glue code
|
||||
const word COFF_IMAGE_REL_PPC_IMGLUE = 0x000E; // symbol is glue code; virtual address is TOC restore instruction
|
||||
const word COFF_IMAGE_REL_PPC_SECREL16 = 0x000F; // va of containing section (limited to 16 bits)
|
||||
const word COFF_IMAGE_REL_PPC_REFHI = 0x0010;
|
||||
const word COFF_IMAGE_REL_PPC_REFLO = 0x0011;
|
||||
const word COFF_IMAGE_REL_PPC_PAIR = 0x0012;
|
||||
const word COFF_IMAGE_REL_PPC_SECRELLO = 0x0013; // Low 16-bit section relative reference (used for >32k TLS)
|
||||
const word COFF_IMAGE_REL_PPC_SECRELHI = 0x0014; // High 16-bit section relative reference (used for >32k TLS)
|
||||
const word COFF_IMAGE_REL_PPC_GPREL = 0x0015;
|
||||
|
||||
const word COFF_IMAGE_REL_PPC_TYPEMASK = 0x00FF; // mask to isolate above values in IMAGE_RELOCATION.Type
|
||||
|
||||
// Flag bits in IMAGE_RELOCATION.TYPE
|
||||
|
||||
const word COFF_IMAGE_REL_PPC_NEG = 0x0100; // subtract reloc value rather than adding it
|
||||
const word COFF_IMAGE_REL_PPC_BRTAKEN = 0x0200; // fix branch prediction bit to predict branch taken
|
||||
const word COFF_IMAGE_REL_PPC_BRNTAKEN = 0x0400; // fix branch prediction bit to predict branch not taken
|
||||
const word COFF_IMAGE_REL_PPC_TOCDEFN = 0x0800; // toc slot defined in file (or, data in toc)
|
||||
|
||||
//
|
||||
// Hitachi SH3 relocation types.
|
||||
//
|
||||
const word COFF_IMAGE_REL_SH3_ABSOLUTE = 0x0000; // No relocation
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT16 = 0x0001; // 16 bit direct
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT32 = 0x0002; // 32 bit direct
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT8 = 0x0003; // 8 bit direct, -128..255
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT8_WORD = 0x0004; // 8 bit direct .W (0 ext.)
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT8_LONG = 0x0005; // 8 bit direct .L (0 ext.)
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT4 = 0x0006; // 4 bit direct (0 ext.)
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT4_WORD = 0x0007; // 4 bit direct .W (0 ext.)
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT4_LONG = 0x0008; // 4 bit direct .L (0 ext.)
|
||||
const word COFF_IMAGE_REL_SH3_PCREL8_WORD = 0x0009; // 8 bit PC relative .W
|
||||
const word COFF_IMAGE_REL_SH3_PCREL8_LONG = 0x000A; // 8 bit PC relative .L
|
||||
const word COFF_IMAGE_REL_SH3_PCREL12_WORD = 0x000B; // 12 LSB PC relative .W
|
||||
const word COFF_IMAGE_REL_SH3_STARTOF_SECTION = 0x000C; // Start of EXE section
|
||||
const word COFF_IMAGE_REL_SH3_SIZEOF_SECTION = 0x000D; // Size of EXE section
|
||||
const word COFF_IMAGE_REL_SH3_SECTION = 0x000E; // Section table index
|
||||
const word COFF_IMAGE_REL_SH3_SECREL = 0x000F; // Offset within section
|
||||
const word COFF_IMAGE_REL_SH3_DIRECT32_NB = 0x0010; // 32 bit direct not based
|
||||
|
||||
const word COFF_IMAGE_REL_ARM_ABSOLUTE = 0x0000; // No relocation required
|
||||
const word COFF_IMAGE_REL_ARM_ADDR32 = 0x0001; // 32 bit address
|
||||
const word COFF_IMAGE_REL_ARM_ADDR32NB = 0x0002; // 32 bit address w/o image base
|
||||
const word COFF_IMAGE_REL_ARM_BRANCH24 = 0x0003; // 24 bit offset << 2 & sign ext.
|
||||
const word COFF_IMAGE_REL_ARM_BRANCH11 = 0x0004; // Thumb: 2 11 bit offsets
|
||||
const word COFF_IMAGE_REL_ARM_SECTION = 0x000E; // Section table index
|
||||
const word COFF_IMAGE_REL_ARM_SECREL = 0x000F; // Offset within section
|
||||
|
||||
//
|
||||
// IA64 relocation types.
|
||||
//
|
||||
|
||||
const word COFF_IMAGE_REL_IA64_ABSOLUTE = 0x0000;
|
||||
const word COFF_IMAGE_REL_IA64_IMM14 = 0x0001;
|
||||
const word COFF_IMAGE_REL_IA64_IMM22 = 0x0002;
|
||||
const word COFF_IMAGE_REL_IA64_IMM64 = 0x0003;
|
||||
const word COFF_IMAGE_REL_IA64_DIR32 = 0x0004;
|
||||
const word COFF_IMAGE_REL_IA64_DIR64 = 0x0005;
|
||||
const word COFF_IMAGE_REL_IA64_PCREL21B = 0x0006;
|
||||
const word COFF_IMAGE_REL_IA64_PCREL21M = 0x0007;
|
||||
const word COFF_IMAGE_REL_IA64_PCREL21F = 0x0008;
|
||||
const word COFF_IMAGE_REL_IA64_GPREL22 = 0x0009;
|
||||
const word COFF_IMAGE_REL_IA64_LTOFF22 = 0x000A;
|
||||
const word COFF_IMAGE_REL_IA64_SECTION = 0x000B;
|
||||
const word COFF_IMAGE_REL_IA64_SECREL22 = 0x000C;
|
||||
const word COFF_IMAGE_REL_IA64_SECREL64I = 0x000D;
|
||||
const word COFF_IMAGE_REL_IA64_SECREL32 = 0x000E;
|
||||
const word COFF_IMAGE_REL_IA64_LTOFF64 = 0x000F;
|
||||
const word COFF_IMAGE_REL_IA64_DIR32NB = 0x0010;
|
||||
const word COFF_IMAGE_REL_IA64_RESERVED_11 = 0x0011;
|
||||
const word COFF_IMAGE_REL_IA64_RESERVED_12 = 0x0012;
|
||||
const word COFF_IMAGE_REL_IA64_RESERVED_13 = 0x0013;
|
||||
const word COFF_IMAGE_REL_IA64_RESERVED_14 = 0x0014;
|
||||
const word COFF_IMAGE_REL_IA64_RESERVED_15 = 0x0015;
|
||||
const word COFF_IMAGE_REL_IA64_RESERVED_16 = 0x0016;
|
||||
const word COFF_IMAGE_REL_IA64_ADDEND = 0x001F;
|
||||
|
||||
const word COFF_IMAGE_REL_BASED_ABSOLUTE = 0;
|
||||
const word COFF_IMAGE_REL_BASED_HIGH = 1;
|
||||
const word COFF_IMAGE_REL_BASED_LOW = 2;
|
||||
const word COFF_IMAGE_REL_BASED_HIGHLOW = 3;
|
||||
const word COFF_IMAGE_REL_BASED_HIGHADJ = 4;
|
||||
const word COFF_IMAGE_REL_BASED_MIPS_JMPADDR = 5;
|
||||
const word COFF_IMAGE_REL_BASED_SECTION = 6;
|
||||
const word COFF_IMAGE_REL_BASED_REL32 = 7;
|
||||
|
||||
const word COFF_IMAGE_REL_BASED_MIPS_JMPADDR16 = 9;
|
||||
const word COFF_IMAGE_REL_BASED_IA64_IMM64 = 9;
|
||||
const word COFF_IMAGE_REL_BASED_DIR64 = 10;
|
||||
const word COFF_IMAGE_REL_BASED_HIGH3ADJ = 11;
|
||||
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_EXPORT = 0; // Export Directory
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_IMPORT = 1; // Import Directory
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_RESOURCE = 2; // Resource Directory
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3; // Exception Directory
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_SECURITY = 4; // Security Directory
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_BASERELOC = 5; // Base Relocation Table
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_DEBUG = 6; // Debug Directory
|
||||
// COFF_IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7; // (X86 usage)
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7; // Architecture Specific Data
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8; // RVA of GP
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_TLS = 9; // TLS Directory
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10; // Load Configuration Directory
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11; // Bound Import Directory in headers
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_IAT = 12; // Import Address Table
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13; // Delay Load Import Descriptors
|
||||
const int COFF_IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14; // COM Runtime descriptor
|
||||
|
||||
struct COFF_IMAGE_RESOURCE_DIRECTORY
|
||||
{
|
||||
dword Characteristics;
|
||||
dword TimeDateStamp;
|
||||
word MajorVersion;
|
||||
word MinorVersion;
|
||||
word NumberOfNamedEntries;
|
||||
word NumberOfIdEntries;
|
||||
// IMAGE_RESOURCE_DIRECTORY_ENTRY DirectoryEntries[];
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
struct COFF_IMAGE_RESOURCE_DIRECTORY_ENTRY
|
||||
{
|
||||
union {
|
||||
struct {
|
||||
dword NameOffset:31;
|
||||
dword NameIsString:1;
|
||||
};
|
||||
dword Name;
|
||||
word Id;
|
||||
};
|
||||
union {
|
||||
dword OffsetToData;
|
||||
struct {
|
||||
dword OffsetToDirectory:31;
|
||||
dword DataIsDirectory:1;
|
||||
};
|
||||
};
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
struct COFF_IMAGE_RESOURCE_DATA_ENTRY
|
||||
{
|
||||
dword OffsetToData;
|
||||
dword Size;
|
||||
dword CodePage;
|
||||
dword Reserved;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
#define COFF_IMAGE_RESOURCE_NAME_IS_STRING 0x80000000
|
||||
#define COFF_IMAGE_RESOURCE_DATA_IS_DIRECTORY 0x80000000
|
||||
|
||||
// GNU stab-specific information
|
||||
|
||||
/* Stabs entries use a 12 byte format:
|
||||
4 byte string table index
|
||||
1 byte stab type
|
||||
1 byte stab other field
|
||||
2 byte stab desc field
|
||||
4 byte stab value
|
||||
FIXME: This will have to change for a 64 bit object format.
|
||||
|
||||
The stabs symbols are divided into compilation units. For the
|
||||
first entry in each unit, the type of 0, the value is the length of
|
||||
the string table for this unit, and the desc field is the number of
|
||||
stabs symbols for this unit. */
|
||||
|
||||
const int STAB_STRDXOFF = 0;
|
||||
const int STAB_TYPEOFF = 4;
|
||||
const int STAB_OTHEROFF = 5;
|
||||
const int STAB_DESCOFF = 6;
|
||||
const int STAB_VALOFF = 8;
|
||||
const int STAB_STABSIZE = 12;
|
||||
|
||||
struct STAB_INFO : Moveable<STAB_INFO>
|
||||
{
|
||||
int strdx;
|
||||
byte type;
|
||||
byte other;
|
||||
word desc;
|
||||
int value;
|
||||
}
|
||||
#ifdef COMPILER_GCC
|
||||
__attribute__((packed))
|
||||
#endif
|
||||
;
|
||||
|
||||
#define __define_stab(NAME, CODE, STRING) NAME=CODE,
|
||||
#define __define_stab_duplicate(NAME, CODE, STRING) NAME=CODE,
|
||||
|
||||
/*
|
||||
enum STAB_DEBUG_CODE
|
||||
{
|
||||
#include "stab.def"
|
||||
LAST_UNUSED_STAB_CODE
|
||||
};
|
||||
|
||||
#undef __define_stab
|
||||
*/
|
||||
|
||||
/* Definitions of "desc" field for N_SO stabs in Solaris2. */
|
||||
|
||||
const int STAB_N_SO_AS = 1;
|
||||
const int STAB_N_SO_C = 2;
|
||||
const int STAB_N_SO_ANSI_C = 3;
|
||||
const int STAB_N_SO_CC = 4; /* C++ */
|
||||
const int STAB_N_SO_FORTRAN = 5;
|
||||
const int STAB_N_SO_PASCAL = 6;
|
||||
|
||||
/* Solaris2: Floating point type values in basic types. */
|
||||
|
||||
const int STAB_NF_NONE = 0;
|
||||
const int STAB_NF_SINGLE = 1; /* IEEE 32-bit */
|
||||
const int STAB_NF_DOUBLE = 2; /* IEEE 64-bit */
|
||||
const int STAB_NF_COMPLEX = 3; /* Fortran complex */
|
||||
const int STAB_NF_COMPLEX16 = 4; /* Fortran double complex */
|
||||
const int STAB_NF_COMPLEX32 = 5; /* Fortran complex*16 */
|
||||
const int STAB_NF_LDOUBLE = 6; /* Long double (whatever that is) */
|
||||
|
||||
#ifdef COMPILER_MSC
|
||||
#pragma pack(pop)
|
||||
#endif
|
||||
|
||||
String COFFSymbolName(const COFF_IMAGE_SYMBOL& sym, const char *strtbl);
|
||||
|
||||
#endif
|
||||
1
uppsrc2/coff/imagehlp.dli
Normal file
1
uppsrc2/coff/imagehlp.dli
Normal file
|
|
@ -0,0 +1 @@
|
|||
FN_C(DWORD, __stdcall, UnDecorateSymbolName, (PCSTR dn, PSTR udn, DWORD len, DWORD Flags))
|
||||
4
uppsrc2/coff/init
Normal file
4
uppsrc2/coff/init
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef _coff_icpp_init_stub
|
||||
#define _coff_icpp_init_stub
|
||||
#include "Core/init"
|
||||
#endif
|
||||
340
uppsrc2/coff/lib.cpp
Normal file
340
uppsrc2/coff/lib.cpp
Normal file
|
|
@ -0,0 +1,340 @@
|
|||
#include "coff.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
|
||||
enum { HEADER_SIZE = sizeof(COFF_IMAGE_ARCHIVE_MEMBER_HEADER) };
|
||||
|
||||
static double ToLibraryTime(Time time)
|
||||
{
|
||||
if(IsNull(time))
|
||||
return Null;
|
||||
SYSTEMTIME tm, tb;
|
||||
Zero(tm); Zero(tb);
|
||||
tm.wYear = time.year; tb.wYear = 1970;
|
||||
tm.wMonth = time.month; tb.wMonth = 1;
|
||||
tm.wDay = time.day; tb.wDay = 1;
|
||||
tm.wHour = time.hour; tb.wHour = 2;
|
||||
tm.wMinute = time.minute;
|
||||
tm.wSecond = time.second;
|
||||
FileTime /*ftl,*/ ftg;
|
||||
SystemTimeToFileTime(&tm, &ftg);
|
||||
// LocalFileTimeToFileTime(&ftl, &ftg);
|
||||
FileTime fbl, fbg;
|
||||
SystemTimeToFileTime(&tb, &fbl);
|
||||
LocalFileTimeToFileTime(&fbl, &fbg);
|
||||
#ifdef PLATFORM_WIN32
|
||||
int64 tg = ftg.dwLowDateTime + (int64(1) << 32) * ftg.dwHighDateTime;
|
||||
int64 bg = fbg.dwLowDateTime + (int64(1) << 32) * fbg.dwHighDateTime;
|
||||
return (double)((tg - bg) / 10000000);
|
||||
#else
|
||||
return tg - bg;
|
||||
#endif
|
||||
}
|
||||
|
||||
ArchiveJob::Object::Object(ArchiveJob& archive, int index, String fn, String od, double ft, int ho, bool nf)
|
||||
: archive(archive), index(index), filename(fn), object_data(od), filetime(ft), newfile(nf), header_offset(ho)
|
||||
{
|
||||
trimmed_name = archive.TrimObjectName(filename);
|
||||
longname_offset = -1;
|
||||
header_offset = -1;
|
||||
}
|
||||
|
||||
void ArchiveJob::Object::ReadObject()
|
||||
{
|
||||
if(archive.verbose)
|
||||
PutStdOut(NFormat("%s: reading object file (%d B)", filename, object_data.GetLength()));
|
||||
const byte *begin = object_data;
|
||||
|
||||
const COFF_IMAGE_FILE_HEADER *header = (const COFF_IMAGE_FILE_HEADER *)begin;
|
||||
const COFF_IMAGE_SYMBOL *symtbl = (const COFF_IMAGE_SYMBOL *)(begin + header->PointerToSymbolTable), *symptr = symtbl;
|
||||
const char *strtbl = (const char *)(symtbl + header->NumberOfSymbols);
|
||||
for(int i = 0; i < (int)header->NumberOfSymbols; i++, symptr++)
|
||||
{
|
||||
if(symptr->StorageClass == COFF_IMAGE_SYM_CLASS_STATIC && symptr->SectionNumber != 0
|
||||
&& symptr->Value == 0 && symptr->NumberOfAuxSymbols >= 1)
|
||||
; // ignore section symbols
|
||||
else if((symptr->StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL || symptr->StorageClass == COFF_IMAGE_SYM_CLASS_STATIC)
|
||||
&& (symptr->SectionNumber != 0 || symptr->Value != 0))
|
||||
archive.AddGlobal(index, COFFSymbolName(*symptr, strtbl));
|
||||
i += symptr->NumberOfAuxSymbols;
|
||||
symptr += symptr->NumberOfAuxSymbols;
|
||||
}
|
||||
}
|
||||
|
||||
ArchiveJob::ArchiveJob()
|
||||
{
|
||||
keep_object_paths = false;
|
||||
use_existing_archive = true;
|
||||
trim_longname_objects = false;
|
||||
skip_duplicates = true;
|
||||
verbose = false;
|
||||
#if defined(CPU_IA32)
|
||||
machine = COFF_IMAGE_FILE_MACHINE_I386;
|
||||
#else
|
||||
machine = COFF_IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
#endif
|
||||
}
|
||||
|
||||
void ArchiveJob::LoadFile(String file)
|
||||
{
|
||||
FileMapping mapping;
|
||||
if(!mapping.Open(file))
|
||||
throw Exc(NFormat("%s: file failed to open", file));
|
||||
objects[AddObject(file, mapping.GetData(0, (dword)mapping.GetFileSize()), mapping.GetTime())].ReadObject();
|
||||
}
|
||||
|
||||
int ArchiveJob::AddObject(String filename, String object_data, Time filetime)
|
||||
{
|
||||
return objects.Add(new Object(*this, objects.GetCount(), filename, object_data,
|
||||
ToLibraryTime(filetime), -1, true)).index;
|
||||
}
|
||||
|
||||
void ArchiveJob::LoadLibrary(String libfile)
|
||||
{
|
||||
FileMapping mapping;
|
||||
if(!mapping.Open(libfile))
|
||||
{
|
||||
if(archive_must_exist)
|
||||
throw Exc(NFormat("%s: archive file failed to open", libfile));
|
||||
if(use_existing_archive && verbose)
|
||||
PutStdOut(NFormat("%s: archive not found", libfile));
|
||||
return;
|
||||
}
|
||||
if(memcmp(~mapping, "!<arch>\n", 8))
|
||||
throw Exc(NFormat("%s: not a valid library file (missing !<arch>\\n header)", libfile));
|
||||
if(verbose)
|
||||
PutStdOut(NFormat("%s: reading archive (%d B)", libfile, mapping.GetFileSize()));
|
||||
|
||||
const byte *ptr = mapping.GetIter(8);
|
||||
const byte *end = mapping.End();
|
||||
const byte *longptr = NULL;
|
||||
while(ptr + HEADER_SIZE <= end)
|
||||
{
|
||||
// if(*ptr == '\n')
|
||||
// ptr++;
|
||||
int offset = int(ptr - mapping.Begin());
|
||||
COFF_IMAGE_ARCHIVE_MEMBER_HEADER hdr;
|
||||
memcpy(&hdr, ptr, sizeof(hdr));
|
||||
ptr += sizeof(hdr);
|
||||
int size = atoi((const char *)hdr.Size);
|
||||
const byte *brk = ptr + ((size + 1) & -2);
|
||||
if(hdr.Name[0] == '/' && hdr.Name[1] == '/')
|
||||
{ // longnames
|
||||
longptr = ptr;
|
||||
}
|
||||
else if(hdr.Name[0] != '/' || hdr.Name[1] != ' ')
|
||||
{ // object
|
||||
const byte *nameptr, *namelim;
|
||||
if(hdr.Name[0] != '/')
|
||||
{
|
||||
nameptr = hdr.Name;
|
||||
namelim = nameptr + __countof(hdr.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
int loff = atoi((const char *)hdr.Name + 1);
|
||||
nameptr = longptr + loff;
|
||||
namelim = end;
|
||||
}
|
||||
const byte *p = nameptr;
|
||||
while(p < namelim && *p && *p != '/')
|
||||
p++;
|
||||
String objname(nameptr, int(p - nameptr));
|
||||
String objdata(ptr, size);
|
||||
char temp[13];
|
||||
memcpy(temp, hdr.Date, 12);
|
||||
temp[12] = 0;
|
||||
double membertime = ScanDouble(temp);
|
||||
const COFF_IMPORT_OBJECT_HEADER *imphdr = (const COFF_IMPORT_OBJECT_HEADER *)ptr;
|
||||
int oindex = objects.GetCount();
|
||||
if(skip_duplicates && FindObject(objname) >= 0)
|
||||
{
|
||||
if(verbose)
|
||||
PutStdOut(NFormat("%s: skipping object '%s' (inserting object with the same name)", libfile, objname));
|
||||
}
|
||||
else
|
||||
{
|
||||
if(imphdr->Sig1 == 0 && imphdr->Sig2 == 0xFFFF)
|
||||
{
|
||||
if(imphdr->Machine != machine)
|
||||
throw Exc(NFormat("%s:%s: invalid machine type (%d) in import library module",
|
||||
libfile, objname, imphdr->Machine));
|
||||
const char *pname = (const char *)ptr + sizeof(COFF_IMPORT_OBJECT_HEADER);
|
||||
AddGlobal(oindex, pname);
|
||||
objects.Add(new Object(*this, oindex, objname, objdata, membertime, offset, false));
|
||||
}
|
||||
else
|
||||
objects.Add(new Object(*this, oindex, objname, objdata, membertime, offset, false)).ReadObject();
|
||||
}
|
||||
}
|
||||
ptr = brk;
|
||||
}
|
||||
}
|
||||
|
||||
String ArchiveJob::TrimObjectName(String objname) const
|
||||
{
|
||||
String out = objname;
|
||||
if(!keep_object_paths)
|
||||
out = GetFileName(out);
|
||||
out = ToLower(out);
|
||||
if(trim_longname_objects && out.GetLength() > 15)
|
||||
{
|
||||
for(int f; out.GetLength() > 15 && ((f = out.Find('/')) >= 0 || (f = out.Find('\\')) >= 0); out.Remove(0, f + 1))
|
||||
;
|
||||
if(out.GetLength() > 15)
|
||||
out.Trim(15);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int ArchiveJob::FindObject(String objname) const
|
||||
{
|
||||
return FindFieldIndex(objects, &Object::trimmed_name, TrimObjectName(objname));
|
||||
}
|
||||
|
||||
void ArchiveJob::BuildLibrary(String libfile, bool keep_archive_backups)
|
||||
{
|
||||
SortGlobals();
|
||||
BuildSymbolIndex();
|
||||
BuildLongNameIndex();
|
||||
CalcArchiveOffsets();
|
||||
WriteArchive(libfile, keep_archive_backups);
|
||||
}
|
||||
|
||||
void ArchiveJob::AddGlobal(int object, String symbol)
|
||||
{
|
||||
if(symbol_names.FindAdd(symbol) >= symbol_objects.GetCount())
|
||||
symbol_objects.Add(object);
|
||||
}
|
||||
|
||||
void ArchiveJob::SortGlobals()
|
||||
{
|
||||
Vector<String> symn = symbol_names.PickKeys();
|
||||
IndexSort(symn, symbol_objects, StdLess<String>());
|
||||
symbol_names = symn;
|
||||
}
|
||||
|
||||
void ArchiveJob::BuildLongNameIndex()
|
||||
{
|
||||
for(int i = 0; i < objects.GetCount(); i++)
|
||||
{
|
||||
String n = objects[i].trimmed_name;
|
||||
if(n.GetLength() >= 16)
|
||||
{
|
||||
objects[i].longname_offset = longnames.GetLength();
|
||||
longnames.Cat(n, n.GetLength() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ArchiveJob::BuildSymbolIndex()
|
||||
{
|
||||
for(int i = 0; i < symbol_names.GetCount(); i++)
|
||||
symbolnames.Cat(symbol_names[i], symbol_names[i].GetLength() + 1);
|
||||
}
|
||||
|
||||
void ArchiveJob::CalcArchiveOffsets()
|
||||
{
|
||||
first_index_offset = 8; // header length
|
||||
first_index_datasize = 4 + 4 * symbol_names.GetCount() + symbolnames.GetLength();
|
||||
second_index_offset = first_index_offset + HEADER_SIZE + ((first_index_datasize + 1) & -2);
|
||||
second_index_datasize = 4 + 4 * objects.GetCount() + 4 + 2 * symbol_names.GetCount() + symbolnames.GetLength();
|
||||
longnames_offset = second_index_offset + HEADER_SIZE + ((second_index_datasize + 1) & -2);
|
||||
archive_length = longnames_offset + HEADER_SIZE + ((longnames.GetLength() + 1) & -2);
|
||||
for(int i = 0; i < objects.GetCount(); i++)
|
||||
{
|
||||
objects[i].header_offset = archive_length;
|
||||
archive_length += HEADER_SIZE + ((objects[i].object_data.GetLength() + 1) & -2);
|
||||
}
|
||||
}
|
||||
|
||||
static void WriteMemberHeader(byte *out, String name, int longname_offset, double time, int size)
|
||||
{
|
||||
memset(out, ' ', sizeof(COFF_IMAGE_ARCHIVE_MEMBER_HEADER));
|
||||
if(longname_offset < 0)
|
||||
{
|
||||
memcpy(out, name, name.GetLength());
|
||||
out[name.GetLength()] = '/';
|
||||
}
|
||||
else
|
||||
{
|
||||
String tmp = FormatInt(longname_offset);
|
||||
out[0] = '/';
|
||||
memcpy(out + 1, tmp, tmp.GetLength());
|
||||
}
|
||||
String tmp = FormatDoubleFix(time, 0);
|
||||
memcpy(out + 16, tmp, min(tmp.GetLength(), 12));
|
||||
out[28] = '0';
|
||||
out[34] = '0';
|
||||
memcpy(out + 40, "100666", 6);
|
||||
tmp = FormatInt(size);
|
||||
memcpy(out + 48, tmp, tmp.GetLength());
|
||||
out[58] = COFF_IMAGE_ARCHIVE_END1;
|
||||
out[59] = COFF_IMAGE_ARCHIVE_END2;
|
||||
if(size & 1)
|
||||
out[HEADER_SIZE + size] = COFF_IMAGE_ARCHIVE_PAD;
|
||||
}
|
||||
|
||||
void ArchiveJob::WriteArchive(String libraryfile, bool keep_archive_backups)
|
||||
{
|
||||
Vector<byte> archive;
|
||||
archive.SetCount(archive_length);
|
||||
memcpy(archive.Begin(), "!<arch>\n", 8);
|
||||
double nulltime = ToLibraryTime(GetSysTime());
|
||||
WriteMemberHeader(archive.GetIter(first_index_offset), "", -1, nulltime, first_index_datasize);
|
||||
WriteMemberHeader(archive.GetIter(second_index_offset), "", -1, nulltime, second_index_datasize);
|
||||
WriteIndex(archive.GetIter(first_index_offset + HEADER_SIZE), archive.GetIter(second_index_offset + HEADER_SIZE));
|
||||
WriteMemberHeader(archive.GetIter(longnames_offset), "/", -1, nulltime, longnames.GetLength());
|
||||
memcpy(archive.GetIter(longnames_offset + HEADER_SIZE), longnames, longnames.GetLength());
|
||||
for(int i = 0; i < objects.GetCount(); i++)
|
||||
{
|
||||
const Object& o = objects[i];
|
||||
WriteMemberHeader(archive.GetIter(o.header_offset), o.trimmed_name, o.longname_offset, o.filetime, o.object_data.GetLength());
|
||||
memcpy(archive.GetIter(o.header_offset + HEADER_SIZE), o.object_data, o.object_data.GetLength());
|
||||
}
|
||||
String tmpfile = libraryfile + ".tmp";
|
||||
String oldfile = libraryfile + ".old";
|
||||
FileOut fo;
|
||||
if(!fo.Open(tmpfile))
|
||||
throw Exc(NFormat("%s: failed to create file", tmpfile));
|
||||
if(verbose)
|
||||
PutStdOut(NFormat("%s: saving updated archive (%d B)", libraryfile, archive_length));
|
||||
fo.Put(archive.Begin(), archive_length);
|
||||
fo.Close();
|
||||
if(fo.IsError())
|
||||
{
|
||||
FileDelete(tmpfile);
|
||||
throw Exc(NFormat("%s: error writing file", tmpfile));
|
||||
}
|
||||
FileDelete(oldfile);
|
||||
FileMove(libraryfile, oldfile);
|
||||
if(!FileMove(tmpfile, libraryfile))
|
||||
throw Exc(NFormat("%s: error replacing %s", tmpfile, libraryfile));
|
||||
if(!keep_archive_backups)
|
||||
FileDelete(oldfile);
|
||||
}
|
||||
|
||||
void ArchiveJob::WriteIndex(byte *first, byte *second)
|
||||
{
|
||||
int nsym = symbol_names.GetCount();
|
||||
Poke32be(first, nsym);
|
||||
first += 4;
|
||||
for(int i = 0; i < nsym; i++, first += 4)
|
||||
Poke32be(first, objects[symbol_objects[i]].header_offset);
|
||||
memcpy(first, symbolnames, symbolnames.GetLength());
|
||||
Poke32le(second, objects.GetCount());
|
||||
second += 4;
|
||||
for(int i = 0; i < objects.GetCount(); i++, second += 4)
|
||||
Poke32le(second, objects[i].header_offset);
|
||||
Poke32le(second, nsym);
|
||||
second += 4;
|
||||
for(int i = 0; i < symbol_names.GetCount(); i++, second += 2)
|
||||
Poke16le(second, symbol_objects[i] + 1);
|
||||
memcpy(second, symbolnames, symbolnames.GetLength());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
88
uppsrc2/coff/lib.h
Normal file
88
uppsrc2/coff/lib.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
#ifndef _coff_lib_h_
|
||||
#define _coff_lib_h_
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
|
||||
class ArchiveJob
|
||||
{
|
||||
protected:
|
||||
class Object;
|
||||
friend class ArchiveJob::Object;
|
||||
|
||||
public:
|
||||
ArchiveJob();
|
||||
|
||||
int AddObject(String filename, String object_data, Time filetime);
|
||||
void AddGlobal(int object, String symbol);
|
||||
|
||||
void SortGlobals();
|
||||
|
||||
void BuildLibrary(String libfile, bool keep_archive_backups);
|
||||
|
||||
protected:
|
||||
void LoadFile(String file);
|
||||
void LoadLibrary(String libfile);
|
||||
int FindObject(String objname) const;
|
||||
String TrimObjectName(String objname) const;
|
||||
|
||||
void WriteArchive(String libfile, bool keep_archive_backups);
|
||||
|
||||
class Object
|
||||
{
|
||||
public:
|
||||
Object(ArchiveJob& archive, int index, String filename, String objdata, double filetime, int header_offset, bool newfile);
|
||||
|
||||
void ReadObject();
|
||||
|
||||
public:
|
||||
ArchiveJob& archive;
|
||||
int index;
|
||||
|
||||
String filename;
|
||||
String trimmed_name;
|
||||
String object_data;
|
||||
double filetime;
|
||||
bool newfile;
|
||||
|
||||
int longname_offset;
|
||||
int header_offset;
|
||||
};
|
||||
|
||||
public:
|
||||
int machine;
|
||||
bool keep_object_paths;
|
||||
bool use_existing_archive;
|
||||
bool archive_must_exist;
|
||||
bool trim_longname_objects;
|
||||
bool skip_duplicates;
|
||||
bool verbose;
|
||||
enum MODE { MODE_MSLIB, MODE_GNUAR };
|
||||
MODE armode;
|
||||
|
||||
protected:
|
||||
Array<Object> objects;
|
||||
Vector<String> object_names;
|
||||
|
||||
Vector<int> symbol_objects;
|
||||
Index<String> symbol_names;
|
||||
|
||||
String longnames;
|
||||
String symbolnames;
|
||||
|
||||
int first_index_offset;
|
||||
int first_index_datasize;
|
||||
int second_index_offset;
|
||||
int second_index_datasize;
|
||||
int longnames_offset;
|
||||
int archive_length;
|
||||
|
||||
private:
|
||||
void BuildLongNameIndex();
|
||||
void BuildSymbolIndex();
|
||||
void CalcArchiveOffsets();
|
||||
void WriteIndex(byte *first, byte *second);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
268
uppsrc2/coff/stab.def
Normal file
268
uppsrc2/coff/stab.def
Normal file
|
|
@ -0,0 +1,268 @@
|
|||
/* Table of DBX symbol codes for the GNU system.
|
||||
Copyright 1988, 1991, 1992, 1993, 1994, 1996, 1998
|
||||
Free Software Foundation, Inc.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
|
||||
|
||||
/* New stab from Solaris 2. This uses an n_type of 0, which in a.out files
|
||||
overlaps the N_UNDF used for ordinary symbols. In ELF files, the
|
||||
debug information is in a different file section, so there is no conflict.
|
||||
This symbol's n_value gives the size of the string section associated
|
||||
with this file. The symbol's n_strx (relative to the just-updated
|
||||
string section start address) gives the name of the source file,
|
||||
e.g. "foo.c", without any path information. The symbol's n_desc gives
|
||||
the count of upcoming symbols associated with this file (not including
|
||||
this one). */
|
||||
/* __define_stab (N_UNDF, 0x00, "UNDF") */
|
||||
|
||||
/* Global variable. Only the name is significant.
|
||||
To find the address, look in the corresponding external symbol. */
|
||||
__define_stab (N_GSYM, 0x20, "GSYM")
|
||||
|
||||
/* Function name for BSD Fortran. Only the name is significant.
|
||||
To find the address, look in the corresponding external symbol. */
|
||||
__define_stab (N_FNAME, 0x22, "FNAME")
|
||||
|
||||
/* Function name or text-segment variable for C. Value is its address.
|
||||
Desc is supposedly starting line number, but GCC doesn't set it
|
||||
and DBX seems not to miss it. */
|
||||
__define_stab (N_FUN, 0x24, "FUN")
|
||||
|
||||
/* Data-segment variable with internal linkage. Value is its address.
|
||||
"Static Sym". */
|
||||
__define_stab (N_STSYM, 0x26, "STSYM")
|
||||
|
||||
/* BSS-segment variable with internal linkage. Value is its address. */
|
||||
__define_stab (N_LCSYM, 0x28, "LCSYM")
|
||||
|
||||
/* Name of main routine. Only the name is significant. */
|
||||
__define_stab (N_MAIN, 0x2a, "MAIN")
|
||||
|
||||
/* Solaris2: Read-only data symbols. */
|
||||
__define_stab (N_ROSYM, 0x2c, "ROSYM")
|
||||
|
||||
/* Global symbol in Pascal.
|
||||
Supposedly the value is its line number; I'm skeptical. */
|
||||
__define_stab (N_PC, 0x30, "PC")
|
||||
|
||||
/* Number of symbols: 0, files,,funcs,lines according to Ultrix V4.0. */
|
||||
__define_stab (N_NSYMS, 0x32, "NSYMS")
|
||||
|
||||
/* "No DST map for sym: name, ,0,type,ignored" according to Ultrix V4.0. */
|
||||
__define_stab (N_NOMAP, 0x34, "NOMAP")
|
||||
|
||||
/* New stab from Solaris 2. Like N_SO, but for the object file. Two in
|
||||
a row provide the build directory and the relative path of the .o from it.
|
||||
Solaris2 uses this to avoid putting the stabs info into the linked
|
||||
executable; this stab goes into the ".stab.index" section, and the debugger
|
||||
reads the real stabs directly from the .o files instead. */
|
||||
__define_stab (N_OBJ, 0x38, "OBJ")
|
||||
|
||||
/* New stab from Solaris 2. Options for the debugger, related to the
|
||||
source language for this module. E.g. whether to use ANSI
|
||||
integral promotions or traditional integral promotions. */
|
||||
__define_stab (N_OPT, 0x3c, "OPT")
|
||||
|
||||
/* Register variable. Value is number of register. */
|
||||
__define_stab (N_RSYM, 0x40, "RSYM")
|
||||
|
||||
/* Modula-2 compilation unit. Can someone say what info it contains? */
|
||||
__define_stab (N_M2C, 0x42, "M2C")
|
||||
|
||||
/* Line number in text segment. Desc is the line number;
|
||||
value is corresponding address. On Solaris2, the line number is
|
||||
relative to the start of the current function. */
|
||||
__define_stab (N_SLINE, 0x44, "SLINE")
|
||||
|
||||
/* Similar, for data segment. */
|
||||
__define_stab (N_DSLINE, 0x46, "DSLINE")
|
||||
|
||||
/* Similar, for bss segment. */
|
||||
__define_stab (N_BSLINE, 0x48, "BSLINE")
|
||||
|
||||
/* Sun's source-code browser stabs. ?? Don't know what the fields are.
|
||||
Supposedly the field is "path to associated .cb file". THIS VALUE
|
||||
OVERLAPS WITH N_BSLINE! */
|
||||
__define_stab_duplicate (N_BROWS, 0x48, "BROWS")
|
||||
|
||||
/* GNU Modula-2 definition module dependency. Value is the modification time
|
||||
of the definition file. Other is non-zero if it is imported with the
|
||||
GNU M2 keyword %INITIALIZE. Perhaps N_M2C can be used if there
|
||||
are enough empty fields? */
|
||||
__define_stab(N_DEFD, 0x4a, "DEFD")
|
||||
|
||||
/* New in Solaris2. Function start/body/end line numbers. */
|
||||
__define_stab(N_FLINE, 0x4C, "FLINE")
|
||||
|
||||
/* THE FOLLOWING TWO STAB VALUES CONFLICT. Happily, one is for Modula-2
|
||||
and one is for C++. Still,... */
|
||||
/* GNU C++ exception variable. Name is variable name. */
|
||||
__define_stab (N_EHDECL, 0x50, "EHDECL")
|
||||
/* Modula2 info "for imc": name,,0,0,0 according to Ultrix V4.0. */
|
||||
__define_stab_duplicate (N_MOD2, 0x50, "MOD2")
|
||||
|
||||
/* GNU C++ `catch' clause. Value is its address. Desc is nonzero if
|
||||
this entry is immediately followed by a CAUGHT stab saying what exception
|
||||
was caught. Multiple CAUGHT stabs means that multiple exceptions
|
||||
can be caught here. If Desc is 0, it means all exceptions are caught
|
||||
here. */
|
||||
__define_stab (N_CATCH, 0x54, "CATCH")
|
||||
|
||||
/* Structure or union element. Value is offset in the structure. */
|
||||
__define_stab (N_SSYM, 0x60, "SSYM")
|
||||
|
||||
/* Solaris2: Last stab emitted for module. */
|
||||
__define_stab (N_ENDM, 0x62, "ENDM")
|
||||
|
||||
/* Name of main source file.
|
||||
Value is starting text address of the compilation.
|
||||
If multiple N_SO's appear, the first to contain a trailing / is the
|
||||
compilation directory. The first to not contain a trailing / is the
|
||||
source file name, relative to the compilation directory. Others (perhaps
|
||||
resulting from cfront) are ignored.
|
||||
On Solaris2, value is undefined, but desc is a source-language code. */
|
||||
|
||||
__define_stab (N_SO, 0x64, "SO")
|
||||
|
||||
/* SunPro F77: Name of alias. */
|
||||
__define_stab (N_ALIAS, 0x6c, "ALIAS")
|
||||
|
||||
/* Automatic variable in the stack. Value is offset from frame pointer.
|
||||
Also used for type descriptions. */
|
||||
__define_stab (N_LSYM, 0x80, "LSYM")
|
||||
|
||||
/* Beginning of an include file. Only Sun uses this.
|
||||
In an object file, only the name is significant.
|
||||
The Sun linker puts data into some of the other fields. */
|
||||
__define_stab (N_BINCL, 0x82, "BINCL")
|
||||
|
||||
/* Name of sub-source file (#include file).
|
||||
Value is starting text address of the compilation. */
|
||||
__define_stab (N_SOL, 0x84, "SOL")
|
||||
|
||||
/* Parameter variable. Value is offset from argument pointer.
|
||||
(On most machines the argument pointer is the same as the frame pointer. */
|
||||
__define_stab (N_PSYM, 0xa0, "PSYM")
|
||||
|
||||
/* End of an include file. No name.
|
||||
This and N_BINCL act as brackets around the file's output.
|
||||
In an object file, there is no significant data in this entry.
|
||||
The Sun linker puts data into some of the fields. */
|
||||
__define_stab (N_EINCL, 0xa2, "EINCL")
|
||||
|
||||
/* Alternate entry point. Value is its address. */
|
||||
__define_stab (N_ENTRY, 0xa4, "ENTRY")
|
||||
|
||||
/* Beginning of lexical block.
|
||||
The desc is the nesting level in lexical blocks.
|
||||
The value is the address of the start of the text for the block.
|
||||
The variables declared inside the block *precede* the N_LBRAC symbol.
|
||||
On Solaris2, the value is relative to the start of the current function. */
|
||||
__define_stab (N_LBRAC, 0xc0, "LBRAC")
|
||||
|
||||
/* Place holder for deleted include file. Replaces a N_BINCL and everything
|
||||
up to the corresponding N_EINCL. The Sun linker generates these when
|
||||
it finds multiple identical copies of the symbols from an include file.
|
||||
This appears only in output from the Sun linker. */
|
||||
__define_stab (N_EXCL, 0xc2, "EXCL")
|
||||
|
||||
/* Modula-2 scope information. Can someone say what info it contains? */
|
||||
__define_stab (N_SCOPE, 0xc4, "SCOPE")
|
||||
|
||||
/* End of a lexical block. Desc matches the N_LBRAC's desc.
|
||||
The value is the address of the end of the text for the block.
|
||||
On Solaris2, the value is relative to the start of the current function. */
|
||||
__define_stab (N_RBRAC, 0xe0, "RBRAC")
|
||||
|
||||
/* Begin named common block. Only the name is significant. */
|
||||
__define_stab (N_BCOMM, 0xe2, "BCOMM")
|
||||
|
||||
/* End named common block. Only the name is significant
|
||||
(and it should match the N_BCOMM). */
|
||||
__define_stab (N_ECOMM, 0xe4, "ECOMM")
|
||||
|
||||
/* Member of a common block; value is offset within the common block.
|
||||
This should occur within a BCOMM/ECOMM pair. */
|
||||
__define_stab (N_ECOML, 0xe8, "ECOML")
|
||||
|
||||
/* Solaris2: Pascal "with" statement: type,,0,0,offset */
|
||||
__define_stab (N_WITH, 0xea, "WITH")
|
||||
|
||||
/* These STAB's are used on Gould systems for Non-Base register symbols
|
||||
or something like that. FIXME. I have assigned the values at random
|
||||
since I don't have a Gould here. Fixups from Gould folk welcome... */
|
||||
__define_stab (N_NBTEXT, 0xF0, "NBTEXT")
|
||||
__define_stab (N_NBDATA, 0xF2, "NBDATA")
|
||||
__define_stab (N_NBBSS, 0xF4, "NBBSS")
|
||||
__define_stab (N_NBSTS, 0xF6, "NBSTS")
|
||||
__define_stab (N_NBLCS, 0xF8, "NBLCS")
|
||||
|
||||
/* Second symbol entry containing a length-value for the preceding entry.
|
||||
The value is the length. */
|
||||
__define_stab (N_LENG, 0xfe, "LENG")
|
||||
|
||||
/* The above information, in matrix format.
|
||||
|
||||
STAB MATRIX
|
||||
_________________________________________________
|
||||
| 00 - 1F are not dbx stab symbols |
|
||||
| In most cases, the low bit is the EXTernal bit|
|
||||
|
||||
| 00 UNDEF | 02 ABS | 04 TEXT | 06 DATA |
|
||||
| 01 |EXT | 03 |EXT | 05 |EXT | 07 |EXT |
|
||||
|
||||
| 08 BSS | 0A INDR | 0C FN_SEQ | 0E WEAKA |
|
||||
| 09 |EXT | 0B | 0D WEAKU | 0F WEAKT |
|
||||
|
||||
| 10 WEAKD | 12 COMM | 14 SETA | 16 SETT |
|
||||
| 11 WEAKB | 13 | 15 | 17 |
|
||||
|
||||
| 18 SETD | 1A SETB | 1C SETV | 1E WARNING|
|
||||
| 19 | 1B | 1D | 1F FN |
|
||||
|
||||
|_______________________________________________|
|
||||
| Debug entries with bit 01 set are unused. |
|
||||
| 20 GSYM | 22 FNAME | 24 FUN | 26 STSYM |
|
||||
| 28 LCSYM | 2A MAIN | 2C ROSYM | 2E |
|
||||
| 30 PC | 32 NSYMS | 34 NOMAP | 36 |
|
||||
| 38 OBJ | 3A | 3C OPT | 3E |
|
||||
| 40 RSYM | 42 M2C | 44 SLINE | 46 DSLINE |
|
||||
| 48 BSLINE*| 4A DEFD | 4C FLINE | 4E |
|
||||
| 50 EHDECL*| 52 | 54 CATCH | 56 |
|
||||
| 58 | 5A | 5C | 5E |
|
||||
| 60 SSYM | 62 ENDM | 64 SO | 66 |
|
||||
| 68 | 6A | 6C ALIAS | 6E |
|
||||
| 70 | 72 | 74 | 76 |
|
||||
| 78 | 7A | 7C | 7E |
|
||||
| 80 LSYM | 82 BINCL | 84 SOL | 86 |
|
||||
| 88 | 8A | 8C | 8E |
|
||||
| 90 | 92 | 94 | 96 |
|
||||
| 98 | 9A | 9C | 9E |
|
||||
| A0 PSYM | A2 EINCL | A4 ENTRY | A6 |
|
||||
| A8 | AA | AC | AE |
|
||||
| B0 | B2 | B4 | B6 |
|
||||
| B8 | BA | BC | BE |
|
||||
| C0 LBRAC | C2 EXCL | C4 SCOPE | C6 |
|
||||
| C8 | CA | CC | CE |
|
||||
| D0 | D2 | D4 | D6 |
|
||||
| D8 | DA | DC | DE |
|
||||
| E0 RBRAC | E2 BCOMM | E4 ECOMM | E6 |
|
||||
| E8 ECOML | EA WITH | EC | EE |
|
||||
| F0 | F2 | F4 | F6 |
|
||||
| F8 | FA | FC | FE LENG |
|
||||
+-----------------------------------------------+
|
||||
* 50 EHDECL is also MOD2.
|
||||
* 48 BSLINE is also BROWS.
|
||||
*/
|
||||
22
uppsrc2/coff/uar/Copying
Normal file
22
uppsrc2/coff/uar/Copying
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 1998, 2014, The U++ Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
ERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
4
uppsrc2/coff/uar/init
Normal file
4
uppsrc2/coff/uar/init
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef _coff_uar_icpp_init_stub
|
||||
#define _coff_uar_icpp_init_stub
|
||||
#include "coff/init"
|
||||
#endif
|
||||
267
uppsrc2/coff/uar/lib.cpp
Normal file
267
uppsrc2/coff/uar/lib.cpp
Normal file
|
|
@ -0,0 +1,267 @@
|
|||
#include "uar.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "lib.h"
|
||||
#include "version.h"
|
||||
|
||||
UARArchiveJob::UARArchiveJob()
|
||||
{
|
||||
dump_flags = 0;
|
||||
delete_source_objects = false;
|
||||
keep_archive_backups = true;
|
||||
nologo = false;
|
||||
}
|
||||
|
||||
String UARArchiveJob::Usage()
|
||||
{
|
||||
return String().Cat()
|
||||
<< NFormat("uar COFF librarian, version %d.%d.r%d, release date %`\n%s",
|
||||
UAR_VERSION_MAJOR, UAR_VERSION_MINOR, UAR_VERSION_RELEASE, UAR_DATE, UAR_COPYRIGHT) << "\n"
|
||||
"\n"
|
||||
"Currently supported MS lib-compatible options:\n"
|
||||
"\n"
|
||||
"-out:<filename> .. name of lib file to produce\n"
|
||||
"-list[:<filename>] .. dump library contents\n"
|
||||
"-nologo .. suppress startup banner (ignored)\n"
|
||||
"-machine:<one-of " << COFFMachineNames() << ">\n"
|
||||
"-verbose .. verbose link process report\n"
|
||||
" (handled as a neutral, not MS-specific option)\n"
|
||||
"\n"
|
||||
"Currently supported GNU ar-compatible options:\n"
|
||||
"\n"
|
||||
"-c .. don't complain when creating new archive\n"
|
||||
" (automatic, warnings shown in verbose mode only)\n"
|
||||
"-d .. remove files from archive\n"
|
||||
"-m .. move files to archive (delete original files)\n"
|
||||
"-p .. print archive contents\n"
|
||||
"-q .. quick append (same as -r in uar)\n"
|
||||
"-r .. replace & insert files in archive\n"
|
||||
"-s .. create archive index (ignored, automatic)\n"
|
||||
"-t .. type archive contents\n"
|
||||
"-x .. extract archive members\n"
|
||||
"\n"
|
||||
"uar-specific options:\n"
|
||||
"\n"
|
||||
"-dumpsym .. display archive symbol table\n"
|
||||
"-demangle .. display demangled symbol table\n"
|
||||
;
|
||||
}
|
||||
|
||||
void UARArchiveJob::ReadCommand(const char *cmd)
|
||||
{
|
||||
ReadCommand(SplitCmdArgs(cmd));
|
||||
}
|
||||
|
||||
void UARArchiveJob::ReadCommand(const Vector<String>& cmdline)
|
||||
{
|
||||
for(int i = 0; i < cmdline.GetCount(); i++)
|
||||
{
|
||||
String arg = cmdline[i];
|
||||
if(*arg == '-' || *arg == '/')
|
||||
{
|
||||
const char *ptr = ~arg + 1;
|
||||
const char *end = ptr;
|
||||
while(*end && *end != ':')
|
||||
end++;
|
||||
String cmd(ptr, end);
|
||||
String lcmd = ToLower(cmd);
|
||||
String val;
|
||||
if(*end == ':')
|
||||
val = end + 1;
|
||||
bool eaten = true;
|
||||
if(lcmd == "out" && !IsNull(val))
|
||||
libraryfile = val;
|
||||
else if(lcmd == "list")
|
||||
{
|
||||
command = CMD_PRINT;
|
||||
printfile = val;
|
||||
}
|
||||
else if(lcmd == "nologo")
|
||||
nologo = true;
|
||||
else if(lcmd == "machine" && !IsNull(val))
|
||||
{
|
||||
val = ToUpper(val);
|
||||
int m = COFFMachineCode(val);
|
||||
if(m == COFF_IMAGE_FILE_MACHINE_UNKNOWN)
|
||||
PutStdOut(NFormat("Unknown machine type: %s; supported machines are: %s", val, COFFMachineNames()));
|
||||
machine = m;
|
||||
}
|
||||
else
|
||||
eaten = false;
|
||||
if(eaten)
|
||||
armode = MODE_MSLIB;
|
||||
else
|
||||
{
|
||||
// if(lcmd == "dumpobj")
|
||||
// dump_flags |= DUMP_OBJECTS;
|
||||
if(lcmd == "dumpsym")
|
||||
dump_flags |= DUMP_SYMBOLS;
|
||||
else if(lcmd == "demangle")
|
||||
dump_flags |= DUMP_SYMBOLS | DUMP_SYMBOLS_DEMANGLED;
|
||||
else if(lcmd == "verbose")
|
||||
verbose = true;
|
||||
else
|
||||
{
|
||||
for(const char *p = ~arg + 1; *p;)
|
||||
switch(*p++)
|
||||
{
|
||||
case 'c': // don't complain when creating archive
|
||||
if(verbose)
|
||||
PutStdOut("option '-c' ignored (automatic)");
|
||||
break;
|
||||
|
||||
case 'd': // delete files
|
||||
command = CMD_REMOVE;
|
||||
break;
|
||||
|
||||
case 'm': // move files
|
||||
command = CMD_ADD;
|
||||
delete_source_objects = true;
|
||||
break;
|
||||
|
||||
case 'p': // print files
|
||||
command = CMD_PRINT;
|
||||
break;
|
||||
|
||||
case 'q': // quick append
|
||||
command = CMD_ADD;
|
||||
break;
|
||||
|
||||
case 'r': // replace & insert
|
||||
command = CMD_ADD;
|
||||
break;
|
||||
|
||||
case 's': // create archive index
|
||||
if(verbose)
|
||||
PutStdOut("option '-s' ignored (automatic)");
|
||||
break;
|
||||
|
||||
case 't': // type contents
|
||||
command = CMD_CONTENTS;
|
||||
break;
|
||||
|
||||
case 'x': // extract
|
||||
command = CMD_EXTRACT;
|
||||
throw Exc("option '-x' not supported (yet)");
|
||||
|
||||
default: throw Exc(NFormat("Invalid command line option: '%s'", arg));
|
||||
}
|
||||
|
||||
armode = MODE_GNUAR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(IsNull(libraryfile))
|
||||
libraryfile = AppendExt(arg, ".a");
|
||||
else
|
||||
{
|
||||
String fn = AppendExt(arg, armode == MODE_GNUAR ? ".o" : ".obj");
|
||||
if(command == CMD_ADD)
|
||||
LoadFile(fn);
|
||||
else
|
||||
object_names.Add(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UARArchiveJob::Build()
|
||||
{
|
||||
if(IsNull(libraryfile))
|
||||
throw Exc("Archive file not specified.");
|
||||
|
||||
archive_must_exist = (command != CMD_ADD && use_existing_archive);
|
||||
if(use_existing_archive)
|
||||
LoadLibrary(libraryfile);
|
||||
|
||||
SortGlobals();
|
||||
|
||||
if(dump_flags & DUMP_SYMBOLS)
|
||||
{
|
||||
PutStdOut(NFormat("%d symbol(s) in %d object file(s)", symbol_names.GetCount(), objects.GetCount()));
|
||||
PutStdOut("Object Symbol");
|
||||
for(int i = 0; i < symbol_names.GetCount(); i++)
|
||||
{
|
||||
String symname = symbol_names[i];
|
||||
if(dump_flags & DUMP_SYMBOLS_DEMANGLED)
|
||||
symname = DemangleName(symname, armode == MODE_MSLIB ? MANGLING_MSC : MANGLING_GCC);
|
||||
PutStdOut(NFormat("%15<s %s", objects[symbol_objects[i]].trimmed_name, symname));
|
||||
}
|
||||
}
|
||||
|
||||
if(command == CMD_CONTENTS || command == CMD_PRINT)
|
||||
{
|
||||
Print();
|
||||
return;
|
||||
}
|
||||
|
||||
if(command == CMD_EXTRACT)
|
||||
{
|
||||
Extract();
|
||||
return;
|
||||
}
|
||||
|
||||
if(command == CMD_REMOVE)
|
||||
Remove();
|
||||
|
||||
if(objects.IsEmpty())
|
||||
PutStdOut(NFormat("%s: empty archive", libraryfile));
|
||||
|
||||
BuildLibrary(libraryfile, keep_archive_backups);
|
||||
if(delete_source_objects) {
|
||||
if(verbose)
|
||||
PutStdOut("Deleting source objects:");
|
||||
for(int i = 0; i < objects.GetCount(); i++)
|
||||
if(objects[i].newfile) {
|
||||
String fn = objects[i].filename;
|
||||
if(verbose)
|
||||
PutStdOut(NFormat("%d: deleting object file", fn));
|
||||
if(!FileDelete(fn))
|
||||
PutStdOut(NFormat("%s: error deleting file", fn));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UARArchiveJob::Remove()
|
||||
{
|
||||
for(int i = 0; i < object_names.GetCount(); i++)
|
||||
{
|
||||
String n = TrimObjectName(object_names[i]);
|
||||
int t = FindFieldIndex(objects, &Object::trimmed_name, n);
|
||||
if(t >= 0)
|
||||
objects.Remove(t);
|
||||
else
|
||||
PutStdOut(NFormat("%s: not found in archive (trimmed name = %s)", object_names[i], n));
|
||||
}
|
||||
}
|
||||
|
||||
void UARArchiveJob::Extract()
|
||||
{
|
||||
for(int i = 0; i < object_names.GetCount(); i++)
|
||||
{
|
||||
String fn = object_names[i], n = TrimObjectName(fn);
|
||||
int t = FindFieldIndex(objects, &Object::trimmed_name, n);
|
||||
if(t >= 0)
|
||||
{
|
||||
if(!SaveFile(fn, objects[t].object_data))
|
||||
throw Exc(NFormat("%s: error writing extracted file (trimmed name = %s)", fn, n));
|
||||
if(verbose)
|
||||
PutStdOut(NFormat("%s: extracted member %s (%d B)", fn, n, objects[t].object_data.GetLength()));
|
||||
}
|
||||
else
|
||||
PutStdOut(NFormat("%s: not found in archive (trimmed name = %s)", fn, n));
|
||||
}
|
||||
}
|
||||
|
||||
void UARArchiveJob::Print()
|
||||
{
|
||||
PutStdOut("Offset Size Time Object");
|
||||
for(int i = 0; i < objects.GetCount(); i++)
|
||||
{
|
||||
const Object& o = objects[i];
|
||||
PutStdOut(NFormat("%10>d %10>d %12>0n %s", o.header_offset, o.object_data.GetLength(), o.filetime, o.filename));
|
||||
if(command == CMD_PRINT)
|
||||
for(int s = 0; s < symbol_names.GetCount(); s++)
|
||||
if(symbol_objects[s] == i)
|
||||
PutStdOut("\t" + symbol_names[s]);
|
||||
}
|
||||
}
|
||||
38
uppsrc2/coff/uar/lib.h
Normal file
38
uppsrc2/coff/uar/lib.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
#ifndef _coff_uar_lib_h_
|
||||
#define _coff_uar_lib_h_
|
||||
|
||||
class UARArchiveJob : public ArchiveJob
|
||||
{
|
||||
public:
|
||||
UARArchiveJob();
|
||||
|
||||
static String Usage();
|
||||
|
||||
void ReadCommand(const char *cmd);
|
||||
void ReadCommand(const Vector<String>& cmdline);
|
||||
|
||||
void Build();
|
||||
|
||||
private:
|
||||
void Print();
|
||||
void Extract();
|
||||
void Remove();
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
DUMP_SYMBOLS = 0x00000001,
|
||||
DUMP_SYMBOLS_DEMANGLED = 0x00000004,
|
||||
};
|
||||
int dump_flags;
|
||||
enum COMMAND { CMD_ADD, CMD_REMOVE, CMD_EXTRACT, CMD_CONTENTS, CMD_PRINT };
|
||||
COMMAND command;
|
||||
|
||||
String libraryfile;
|
||||
String printfile;
|
||||
bool delete_source_objects;
|
||||
bool keep_archive_backups;
|
||||
bool nologo;
|
||||
};
|
||||
|
||||
#endif
|
||||
91
uppsrc2/coff/uar/main.cpp
Normal file
91
uppsrc2/coff/uar/main.cpp
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
#include "uar.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "lib.h"
|
||||
|
||||
static void TryMain()
|
||||
{
|
||||
#ifndef flagTEST
|
||||
if(CommandLine().IsEmpty())
|
||||
{
|
||||
PutStdOut(UARArchiveJob::Usage());
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
UARArchiveJob archjob;
|
||||
archjob.ReadCommand(
|
||||
#ifdef flagTEST
|
||||
|
||||
"-sr "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\CtrlLib.a\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\LabelBase.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Button.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Switch.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\EditField.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Text.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\LineEdit.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\DocEdit.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ScrollBar.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\HeaderCtrl.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ArrayCtrl.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\MultiButton.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\PopupTable.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\DropList.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\DropChoice.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Static.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Splitter.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\FrameSplitter.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\SliderCtrl.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ColumnList.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Progress.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\AKeys.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\RichTextView.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Prompt.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Help.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\DateTimeCtrl.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Bar.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\MenuItem.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\MenuBar.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ToolButton.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ToolBar.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ToolTip.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\StatusBar.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\TabCtrl.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\TreeCtrl.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\DlgColor.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ColorPopup.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ColorPusher.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\FileList.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\FileSel.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\PrinterJob.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Windows.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Win32.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\TrayIconWin32.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\TrayIconX11.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\CtrlUtil.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Update.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\LNGCtrl.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\Ch.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ChWin32.o\" "
|
||||
"\"C:/upp0802/out/CtrlLib/MINGW.Gui\\ChGtk.o\" "
|
||||
|
||||
#else
|
||||
CommandLine()
|
||||
#endif
|
||||
);
|
||||
archjob.Build();
|
||||
}
|
||||
|
||||
CONSOLE_APP_MAIN
|
||||
{
|
||||
try
|
||||
{
|
||||
TryMain();
|
||||
}
|
||||
catch(Exc e)
|
||||
{
|
||||
puts(e);
|
||||
SetExitCode(1);
|
||||
}
|
||||
}
|
||||
8
uppsrc2/coff/uar/uar.h
Normal file
8
uppsrc2/coff/uar/uar.h
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef _coff_uar_uar_h_
|
||||
#define _coff_uar_uar_h_
|
||||
|
||||
#include <coff/coff.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
#endif
|
||||
22
uppsrc2/coff/uar/uar.upp
Normal file
22
uppsrc2/coff/uar/uar.upp
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
description "Ultimate++ COFF archiver (GNU binutils compatible, faster)";
|
||||
|
||||
uses
|
||||
coff;
|
||||
|
||||
target(!DEBUG !TEST) ar.exe;
|
||||
|
||||
link(GCC) "-Xlinker -dumpcommand";
|
||||
|
||||
file
|
||||
uar.h,
|
||||
version.h,
|
||||
lib.h,
|
||||
lib.cpp,
|
||||
main.cpp,
|
||||
Info readonly separator,
|
||||
Copying;
|
||||
|
||||
mainconfig
|
||||
"" = "",
|
||||
"" = ".TEST";
|
||||
|
||||
10
uppsrc2/coff/uar/version.h
Normal file
10
uppsrc2/coff/uar/version.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef _coff_uar_version_h_
|
||||
#define _coff_uar_version_h_
|
||||
|
||||
#define UAR_VERSION_MAJOR 1
|
||||
#define UAR_VERSION_MINOR 0
|
||||
#define UAR_VERSION_RELEASE 4
|
||||
#define UAR_DATE Date(2008, 3, 25)
|
||||
#define UAR_COPYRIGHT "Copyright (c) 2003,2004,2008 Tomas Rylek"
|
||||
|
||||
#endif
|
||||
22
uppsrc2/coff/uld/Copying
Normal file
22
uppsrc2/coff/uld/Copying
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
Copyright (c) 1998, 2014, The U++ Project
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials provided
|
||||
with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
ERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
128
uppsrc2/coff/uld/diff
Normal file
128
uppsrc2/coff/uld/diff
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
-------- linkjob.cpp
|
||||
[B] linkjob.err(117): 1 lines inserted
|
||||
+verbose = false;
|
||||
[B] linkjob.err(266): 1 lines inserted
|
||||
+"-verbose .. display additional link information\n"
|
||||
[B] linkjob.err(487): 2 lines inserted
|
||||
+else if(lcmd == "verbose")
|
||||
+verbose = true;
|
||||
[B] linkjob.err(682): 2 lines inserted
|
||||
+if(verbose)
|
||||
+PutConsole(NFormat("%s: loading object file", file));
|
||||
[B] linkjob.err(697): 2 lines inserted
|
||||
+if(verbose)
|
||||
+PutConsole(NFormat("%s: loading static library", file));
|
||||
[B] linkjob.err(886): 2 lines inserted
|
||||
+if(verbose)
|
||||
+PutConsole(NFormat("%s: loading shared library", file));
|
||||
[B] linkjob.err(1998): 2 lines inserted
|
||||
+else if(sec_atom == rsrc_atom)
|
||||
+sx = GRP_RSRC;
|
||||
[A] linkjob.cpp(2072): 7 lines deleted
|
||||
-int last = groups[i + 1].first_section - 1;
|
||||
-const Section& lastsec = section_map[last];
|
||||
-// const ObjectFile::Section& oflast = GetSection(lastsec.obj_sec);
|
||||
-while(last >= first && section_map[last].obj_sec.section == 0)
|
||||
-last--;
|
||||
-const Section *rawsec = (last >= first ? §ion_map[last] : NULL);
|
||||
-// const ObjectFile::Section& ofsec = GetSection(sec.obj_sec);
|
||||
[A] linkjob.cpp(2081): 1 lines replaced
|
||||
-groups[i].raw_size = rawsec ? rawsec->rva + GetSection(rawsec->obj_sec).size - sec.rva : 0;
|
||||
[B] linkjob.err(2086): 22 replacement lines
|
||||
+int last = groups[i + 1].first_section - 1;
|
||||
+if(last >= first)
|
||||
+{
|
||||
+const Section& lastsec = section_map[last];
|
||||
+// if(i != GRP_UDATA)
|
||||
+{
|
||||
+// const ObjectFile::Section& oflast = GetSection(lastsec.obj_sec);
|
||||
+/*
|
||||
+while(last >= first)
|
||||
+{
|
||||
+const ObjectFile::Section& ofsec = GetSection(section_map[last].obj_sec);
|
||||
+if(ofsec.offset)
|
||||
+break;
|
||||
+last--;
|
||||
+}
|
||||
+const Section *rawsec = (last >= first ? §ion_map[last] : NULL);
|
||||
+*/
|
||||
+// const ObjectFile::Section& ofsec = GetSection(sec.obj_sec);
|
||||
+// groups[i].raw_size = rawsec ? rawsec->rva + GetSection(rawsec->obj_sec).size - sec.rva : 0;
|
||||
+groups[i].raw_size = lastsec.rva + GetSection(lastsec.obj_sec).size - sec.rva;
|
||||
+rfa = (rfa + groups[i].raw_size + file_align - 1) & -file_align;
|
||||
+}
|
||||
[A] linkjob.cpp(2083): 1 lines replaced
|
||||
-rfa = (rfa + groups[i].raw_size + file_align - 1) & -file_align;
|
||||
[B] linkjob.err(2109): 1 replacement lines
|
||||
+}
|
||||
[A] linkjob.cpp(2492): 1 lines replaced
|
||||
-sechdr.SizeOfRawData = 0;
|
||||
[B] linkjob.err(2518): 3 replacement lines
|
||||
+// sechdr.SizeOfRawData = (first.group == GRP_UDATA ? 0 : (sechdr.Misc.VirtualSize + file_align - 1) & -file_align);
|
||||
+sechdr.SizeOfRawData = (sechdr.Misc.VirtualSize + file_align - 1) & -file_align;
|
||||
+/*
|
||||
[A] linkjob.cpp(2496): 1 lines replaced
|
||||
-if(chk.obj_sec.section != 0)
|
||||
[B] linkjob.err(2524): 2 replacement lines
|
||||
+const ObjectFile::Section& ofsec = GetSection(chk.obj_sec);
|
||||
+if(ofsec.offset)
|
||||
[A] linkjob.cpp(2498): 1 lines deleted
|
||||
-const ObjectFile::Section& ofsec = GetSection(chk.obj_sec);
|
||||
[B] linkjob.err(2531): 2 lines inserted
|
||||
+sechdr.SizeOfRawData = (sechdr.SizeOfRawData + file_align - 1) & -file_align;
|
||||
+*/
|
||||
[A] linkjob.cpp(2527): 1 lines replaced
|
||||
-stab.Misc.VirtualSize = stab.SizeOfRawData = output_stab_info.GetCount();
|
||||
[B] linkjob.err(2557): 2 replacement lines
|
||||
+stab.Misc.VirtualSize = output_stab_info.GetCount();
|
||||
+stab.SizeOfRawData = (stab.Misc.VirtualSize + file_align - 1) & -file_align;
|
||||
[A] linkjob.cpp(2540): 1 lines replaced
|
||||
-stabstr.Misc.VirtualSize = stabstr.SizeOfRawData = output_stab_strings.GetCount();
|
||||
[B] linkjob.err(2571): 2 replacement lines
|
||||
+stabstr.Misc.VirtualSize = output_stab_strings.GetCount();
|
||||
+stabstr.SizeOfRawData = (stabstr.Misc.VirtualSize + file_align - 1) & -file_align;
|
||||
[A] linkjob.cpp(2554): 1 lines replaced
|
||||
-sym.Misc.VirtualSize = sym.SizeOfRawData = coff_output_symbols.GetCount() * sizeof(COFF_IMAGE_SYMBOL)
|
||||
[B] linkjob.err(2586): 1 replacement lines
|
||||
+sym.Misc.VirtualSize = coff_output_symbols.GetCount() * sizeof(COFF_IMAGE_SYMBOL)
|
||||
[B] linkjob.err(2588): 1 lines inserted
|
||||
+sym.SizeOfRawData = (sym.Misc.VirtualSize + file_align - 1) & -file_align;
|
||||
[A] linkjob.cpp(2570): 1 lines replaced
|
||||
-reloc.Misc.VirtualSize = reloc.SizeOfRawData = output_fixups.GetCount();
|
||||
[B] linkjob.err(2603): 2 replacement lines
|
||||
+reloc.Misc.VirtualSize = output_fixups.GetCount();
|
||||
+reloc.SizeOfRawData = (reloc.Misc.VirtualSize + file_align - 1) & -file_align;
|
||||
[B] linkjob.err(2722): 1 lines inserted
|
||||
+if(verbose)
|
||||
[B] linkjob.err(3087): 5 lines inserted
|
||||
+const ObjectFile::Section& ofsec = GetSection(sec.obj_sec);
|
||||
+// if(/*ofsec.type == ObjectFile::SEC_INULL ||*/ sec.group == GRP_UDATA)
|
||||
+// continue;
|
||||
+if(ofsec.type == ObjectFile::SEC_ANON_COMDAT)
|
||||
+continue;
|
||||
[A] linkjob.cpp(3053): 3 lines deleted
|
||||
-const ObjectFile::Section& ofsec = GetSection(sec.obj_sec);
|
||||
-if(/*ofsec.type == ObjectFile::SEC_INULL ||*/ ofsec.type == ObjectFile::SEC_ANON_COMDAT)
|
||||
-continue;
|
||||
[A] linkjob.cpp(3058): 1 lines deleted
|
||||
-if(ofsec.offset)
|
||||
[A] linkjob.cpp(3393): 7 lines replaced
|
||||
-case GRP_CODE: return "CODE";
|
||||
-case GRP_RDATA: return "RDATA";
|
||||
-case GRP_EDATA: return "EDATA";
|
||||
-case GRP_IDATA: return "IDATA";
|
||||
-case GRP_DATA: return "DATA";
|
||||
-case GRP_UDATA: return "BSS";
|
||||
-case GRP_DEBUG: return "DEBUG";
|
||||
[B] linkjob.err(3429): 11 replacement lines
|
||||
+case GRP_CODE: return "CODE";
|
||||
+case GRP_RDATA: return "RDATA";
|
||||
+case GRP_EDATA: return "EDATA";
|
||||
+case GRP_IDATA: return "IDATA";
|
||||
+case GRP_DATA: return "DATA";
|
||||
+case GRP_UDATA: return "BSS";
|
||||
+case GRP_DEBUG: return "DEBUG";
|
||||
+case GRP_RSRC: return "RSRC";
|
||||
+case GRP_STAB: return "STAB";
|
||||
+case GRP_STABSTR: return "STABSTR";
|
||||
+case GRP_SYMBOLS: return "SYMBOLS";
|
||||
231
uppsrc2/coff/uld/dump.cpp
Normal file
231
uppsrc2/coff/uld/dump.cpp
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
#include "uld.h"
|
||||
#pragma hdrstop
|
||||
|
||||
class FileDump
|
||||
{
|
||||
public:
|
||||
FileDump() : dump_stabs(false), dump_globals(false) {}
|
||||
|
||||
void Run(const char *fn);
|
||||
|
||||
private:
|
||||
void RunCOFF();
|
||||
void RunSymbols(int symoff, int symcnt);
|
||||
void RunStab(int staboff, int stablen, int stroff, int strlen);
|
||||
|
||||
private:
|
||||
String filename;
|
||||
FileMapping mapping;
|
||||
int ne_offset;
|
||||
bool dump_stabs;
|
||||
bool dump_globals;
|
||||
};
|
||||
|
||||
void FileDump::RunSymbols(int symoff, int symcnt)
|
||||
{
|
||||
const COFF_IMAGE_SYMBOL *sym = (COFF_IMAGE_SYMBOL *)&mapping[symoff];
|
||||
const COFF_IMAGE_SYMBOL *end = sym + symcnt;
|
||||
const char *strtbl = (const char *)end;
|
||||
puts(NFormat("Global symbol table (%d entries)", symcnt));
|
||||
puts("Sect Value Type Cl Name");
|
||||
for(; sym < end; sym++)
|
||||
{
|
||||
puts(NFormat("%4>04x %08x %04x %02x %s",
|
||||
sym->SectionNumber, (int)sym->Value, sym->Type, sym->StorageClass, COFFSymbolName(*sym, strtbl)));
|
||||
if(sym->NumberOfAuxSymbols)
|
||||
{
|
||||
if(sym->StorageClass == COFF_IMAGE_SYM_CLASS_FILE)
|
||||
puts(NFormat("\tFile: %s", (const char *)(sym + 1)));
|
||||
}
|
||||
sym += sym->NumberOfAuxSymbols;
|
||||
}
|
||||
}
|
||||
|
||||
void FileDump::RunStab(int staboff, int stablen, int stabstroff, int stabstrlen)
|
||||
{
|
||||
int entries = stablen / STAB_STABSIZE;
|
||||
puts(NFormat("STAB debug info (%d entries)", entries));
|
||||
const STAB_INFO *info = (const STAB_INFO *)&mapping[staboff];
|
||||
const char *str = (const char *)&mapping[stabstroff];
|
||||
int counts[256], sizes[256];
|
||||
ZeroArray(counts);
|
||||
ZeroArray(sizes);
|
||||
int strtotal = 0;
|
||||
static VectorMap<String, int> old_histogram;
|
||||
VectorMap<String, int> histogram;
|
||||
for(int i = 0; i < entries; i++, info++)
|
||||
{
|
||||
counts[info->type]++;
|
||||
int sl = strlen(str + info->strdx) + 1;
|
||||
sizes[info->type] += sl;
|
||||
strtotal += sl;
|
||||
puts(NFormat("%06x %02x %02x %04x %08x %s",
|
||||
i, info->type, info->other, info->desc, info->value, str + info->strdx));
|
||||
String hentry = NFormat("%02x %02x %04x %08x %s", info->type, info->other, info->desc, 0/*info->value*/, str + info->strdx);
|
||||
histogram.GetAdd(hentry, 0)++;
|
||||
}
|
||||
puts(NFormat("%d B, compressed %d B = %d%%",
|
||||
strtotal, stabstrlen, 100 * (1 - stabstrlen / double(max(strtotal, 1)))));
|
||||
for(int i = 0; i < 256; i++)
|
||||
if(counts[i])
|
||||
puts(NFormat("[%02x]: %6>d times, %8>d B", i, counts[i], sizes[i]));
|
||||
puts("\nHistogram:");
|
||||
Vector<int> order = GetSortOrder(histogram.GetValues(), StdGreater<int>());
|
||||
for(int i = 0; i < order.GetCount(); i++)
|
||||
puts(NFormat("%4>d * %s", histogram[order[i]], histogram.GetKey(order[i])));
|
||||
if(!old_histogram.IsEmpty())
|
||||
{
|
||||
puts("\nDifferential histogram:");
|
||||
VectorMap<String, int> diff;
|
||||
diff <<= histogram;
|
||||
for(int i = 0; i < old_histogram.GetCount(); i++)
|
||||
diff.GetAdd(old_histogram.GetKey(i), 0) -= old_histogram[i];
|
||||
for(int i = diff.GetCount(); --i >= 0;)
|
||||
if(!diff[i])
|
||||
diff.Remove(i);
|
||||
order = GetSortOrder(diff.GetValues(), StdGreater<int>());
|
||||
for(int i = 0; i < order.GetCount(); i++)
|
||||
{
|
||||
String key = diff.GetKey(order[i]);
|
||||
puts(NFormat("(%4>d) %4>~d <- %4>~d * %s", diff[order[i]], histogram.Get(key, Null), old_histogram.Get(key, Null), key));
|
||||
}
|
||||
}
|
||||
old_histogram = histogram;
|
||||
}
|
||||
|
||||
void FileDump::RunCOFF()
|
||||
{
|
||||
const COFF_IMAGE_FILE_HEADER *hdr = (const COFF_IMAGE_FILE_HEADER *)&mapping[ne_offset + 4];
|
||||
puts(NFormat("File: %s", filename));
|
||||
puts(NFormat("File size: %d B", mapping.GetFileSize()));
|
||||
const MachineInfo *mach = COFFMachineList();
|
||||
while(mach->name && mach->code != hdr->Machine)
|
||||
mach++;
|
||||
puts(NFormat("Machine: 0x%04x (%s)", hdr->Machine, mach->name));
|
||||
puts(NFormat("NumberOfSections: %d", hdr->NumberOfSections));
|
||||
time_t stamp = hdr->TimeDateStamp;
|
||||
puts(NFormat("TimeDateStamp: 0x%08x, (%s)", (int)hdr->TimeDateStamp, asctime(localtime(&stamp))));
|
||||
puts(NFormat("PointerToSymbolTable: 0x%08x", (int)hdr->PointerToSymbolTable));
|
||||
puts(NFormat("NumberOfSymbols: %d", (int)hdr->NumberOfSymbols));
|
||||
puts(NFormat("SizeOfOptionalHeader: %d", hdr->SizeOfOptionalHeader));
|
||||
puts(NFormat("Characteristics: 0x%08x", hdr->Characteristics));
|
||||
if(hdr->SizeOfOptionalHeader < sizeof(COFF_IMAGE_OPTIONAL_HEADER32))
|
||||
return;
|
||||
|
||||
const COFF_IMAGE_OPTIONAL_HEADER32 *opthdr = (const COFF_IMAGE_OPTIONAL_HEADER32 *)
|
||||
&mapping[ne_offset + 4 + sizeof(COFF_IMAGE_FILE_HEADER)];
|
||||
|
||||
puts(NFormat("Magic: 0x%08x", opthdr->Magic));
|
||||
puts(NFormat("MajorLinkerVersion: %d", opthdr->MajorLinkerVersion));
|
||||
puts(NFormat("MinorLinkerVersion: %d", opthdr->MinorLinkerVersion));
|
||||
puts(NFormat("SizeOfCode: 0x%08x", (int)opthdr->SizeOfCode));
|
||||
puts(NFormat("SizeOfInitializedData: 0x%08x", (int)opthdr->SizeOfInitializedData));
|
||||
puts(NFormat("SizeOfUninitializedData: 0x%08x", (int)opthdr->SizeOfUninitializedData));
|
||||
puts(NFormat("AddressOfEntryPoint: 0x%08x", (int)opthdr->AddressOfEntryPoint));
|
||||
puts(NFormat("BaseOfCode: 0x%08x", (int)opthdr->BaseOfCode));
|
||||
puts(NFormat("BaseOfData: 0x%08x", (int)opthdr->BaseOfData));
|
||||
puts(NFormat("ImageBase: 0x%08x", (int)opthdr->ImageBase));
|
||||
puts(NFormat("SectionAlignment: 0x%08x", (int)opthdr->SectionAlignment));
|
||||
puts(NFormat("FileAlignment: 0x%08x", (int)opthdr->FileAlignment));
|
||||
puts(NFormat("MajorOperatingSystemVersion: %d", opthdr->MajorOperatingSystemVersion));
|
||||
puts(NFormat("MinorOperatingSystemVersion: %d", opthdr->MinorOperatingSystemVersion));
|
||||
puts(NFormat("MajorImageVersion: %d", opthdr->MajorImageVersion));
|
||||
puts(NFormat("MinorImageVersion: %d", opthdr->MinorImageVersion));
|
||||
puts(NFormat("MajorSubsystemVersion: %d", opthdr->MajorSubsystemVersion));
|
||||
puts(NFormat("MinorSubsystemVersion: %d", opthdr->MinorSubsystemVersion));
|
||||
puts(NFormat("Win32VersionValue: %d", (int)opthdr->Win32VersionValue));
|
||||
puts(NFormat("SizeOfImage: 0x%08x", (int)opthdr->SizeOfImage));
|
||||
puts(NFormat("SizeOfHeaders: 0x%08x", (int)opthdr->SizeOfHeaders));
|
||||
puts(NFormat("CheckSum: 0x%08x", (int)opthdr->CheckSum));
|
||||
puts(NFormat("Subsystem: %d", opthdr->Subsystem));
|
||||
puts(NFormat("DllCharacteristics: 0x%08x", opthdr->DllCharacteristics));
|
||||
puts(NFormat("SizeOfStackReserve: 0x%08x", (int)opthdr->SizeOfStackReserve));
|
||||
puts(NFormat("SizeOfStackCommit: 0x%08x", (int)opthdr->SizeOfStackCommit));
|
||||
puts(NFormat("SizeOfHeapReserve: 0x%08x", (int)opthdr->SizeOfHeapReserve));
|
||||
puts(NFormat("SizeOfHeapCommit: 0x%08x", (int)opthdr->SizeOfHeapCommit));
|
||||
puts(NFormat("LoaderFlags: 0x%08x", (int)opthdr->LoaderFlags));
|
||||
puts(NFormat("NumberOfRvaAndSizes: %d", (int)opthdr->NumberOfRvaAndSizes));
|
||||
const COFF_IMAGE_DATA_DIRECTORY *dir = opthdr->DataDirectory;
|
||||
puts("Index RVA Size");
|
||||
int i;
|
||||
for(i = 0; i < (int)opthdr->NumberOfRvaAndSizes; i++, dir++)
|
||||
if(dir->VirtualAddress || dir->Size)
|
||||
puts(NFormat("0x%02x 0x%08x 0x%08x", i, (int)dir->VirtualAddress, (int)dir->Size));
|
||||
const COFF_IMAGE_SECTION_HEADER *sechdr = (const COFF_IMAGE_SECTION_HEADER *)dir;
|
||||
puts("# Section RVA RFA Size PtrData PtrReloc NumReloc PtrLineNo NumLineNo Char");
|
||||
int stab_rfa = 0, stabstr_rfa = 0, stab_len = 0, stabstr_len;
|
||||
for(i = 0; i < hdr->NumberOfSections; i++, sechdr++)
|
||||
{
|
||||
char temp[9];
|
||||
temp[8] = 0;
|
||||
memcpy(temp, sechdr->Name, COFF_IMAGE_SIZEOF_SHORT_NAME);
|
||||
if(!strcmp(temp, ".stab"))
|
||||
{
|
||||
stab_rfa = sechdr->PointerToRawData;
|
||||
stab_len = sechdr->Misc.VirtualSize;
|
||||
}
|
||||
else if(!strcmp(temp, ".stabstr"))
|
||||
{
|
||||
stabstr_rfa = sechdr->PointerToRawData;
|
||||
stabstr_len = sechdr->Misc.VirtualSize;
|
||||
}
|
||||
String line;
|
||||
line
|
||||
<< NFormat("%2<d %8<s 0x%08x 0x%08x 0x%08x ",
|
||||
i + 1,
|
||||
temp,
|
||||
(int)sechdr->VirtualAddress,
|
||||
(int)sechdr->PointerToRawData,
|
||||
(int)sechdr->Misc.VirtualSize)
|
||||
<< NFormat("0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x",
|
||||
(int)sechdr->PointerToRawData,
|
||||
(int)sechdr->PointerToRelocations, (int)sechdr->NumberOfRelocations,
|
||||
(int)sechdr->PointerToLinenumbers, (int)sechdr->NumberOfLinenumbers,
|
||||
(int)sechdr->Characteristics);
|
||||
puts(line);
|
||||
}
|
||||
if(dump_globals && hdr->PointerToSymbolTable)
|
||||
RunSymbols(hdr->PointerToSymbolTable, hdr->NumberOfSymbols);
|
||||
if(dump_stabs && stab_rfa > 0 && stabstr_rfa > 0)
|
||||
RunStab(stab_rfa, stab_len, stabstr_rfa, stabstr_len);
|
||||
}
|
||||
|
||||
void FileDump::Run(const char *fn)
|
||||
{
|
||||
for(;;)
|
||||
if(!memicmp(fn, "stab;", 5))
|
||||
{
|
||||
fn += 5;
|
||||
dump_stabs = true;
|
||||
}
|
||||
else if(!memicmp(fn, "global;", 7))
|
||||
{
|
||||
fn += 7;
|
||||
dump_globals = true;
|
||||
}
|
||||
else
|
||||
break;
|
||||
filename = fn;
|
||||
if(!mapping.Open(filename = fn))
|
||||
throw Exc("file failed to open");
|
||||
if(mapping.GetCount() >= 0x40 && mapping[0] == 'M' && mapping[1] == 'Z'
|
||||
&& (ne_offset = PeekIL(&mapping[0x3C])) >= 0x40 && ne_offset < mapping.GetFileSize()
|
||||
&& PeekIL(&mapping[ne_offset]) == 'P' + 256 * 'E')
|
||||
{
|
||||
RunCOFF();
|
||||
return;
|
||||
}
|
||||
throw Exc("unknown file format");
|
||||
}
|
||||
|
||||
void DumpFile(String fn)
|
||||
{
|
||||
try
|
||||
{
|
||||
FileDump().Run(fn);
|
||||
}
|
||||
catch(Exc e)
|
||||
{
|
||||
throw Exc(NFormat("%s: %s", fn, e));
|
||||
}
|
||||
}
|
||||
4
uppsrc2/coff/uld/init
Normal file
4
uppsrc2/coff/uld/init
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef _coff_uld_icpp_init_stub
|
||||
#define _coff_uld_icpp_init_stub
|
||||
#include "coff/init"
|
||||
#endif
|
||||
3858
uppsrc2/coff/uld/linkjob.cpp
Normal file
3858
uppsrc2/coff/uld/linkjob.cpp
Normal file
File diff suppressed because it is too large
Load diff
118
uppsrc2/coff/uld/main.cpp
Normal file
118
uppsrc2/coff/uld/main.cpp
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
#include "uld.h"
|
||||
#pragma hdrstop
|
||||
#include "obj.h"
|
||||
|
||||
void TryMain()
|
||||
{
|
||||
// PutConsole("ULD::TryMain");
|
||||
int start = msecs();
|
||||
LinkJob linkjob;
|
||||
String cfgfile = LoadFile(ForceExt(GetExeFilePath(), ".cfg"));
|
||||
|
||||
#ifndef flagTEST
|
||||
if(CommandLine().IsEmpty())
|
||||
{
|
||||
PutStdOut(LinkJob::Usage());
|
||||
return;
|
||||
}
|
||||
|
||||
linkjob.ReadCommand(cfgfile, false);
|
||||
linkjob.ReadCommand(CommandLine(), true);
|
||||
linkjob.Link();
|
||||
#else
|
||||
//*
|
||||
linkjob.ReadCommand(
|
||||
|
||||
"--subsystem "
|
||||
"windows "
|
||||
"-Bstatic "
|
||||
"-o "
|
||||
"C:\\upp0802\\out\\MINGW.Gui\\HelloWorld.exe "
|
||||
"c:/upp0802/mingw/bin/../lib/gcc/mingw32/4.3.0/../../../crt2.o "
|
||||
"c:/upp0802/mingw/bin/../lib/gcc/mingw32/4.3.0/crtbegin.o "
|
||||
"-LC:\\upp0802\\mingw\\lib "
|
||||
"-Lc:/upp0802/mingw/bin/../lib/gcc/mingw32/4.3.0 "
|
||||
"-Lc:/upp0802/mingw/bin/../lib/gcc "
|
||||
"-Lc:/upp0802/mingw/bin/../lib/gcc/mingw32/4.3.0/../../.. "
|
||||
"-s "
|
||||
"-O "
|
||||
"2 "
|
||||
"C:/upp0802/out/HelloWorld/MINGW.Gui.Main\\hello.o "
|
||||
"C:/upp0802/out/CtrlLib/MINGW.Gui\\CtrlLib.o "
|
||||
"C:/upp0802/out/CtrlCore/MINGW.Gui\\CtrlCore.o "
|
||||
"C:/upp0802/out/RichText/MINGW.Gui\\RichImage.o "
|
||||
"C:/upp0802/out/plugin/bmp/MINGW.Gui\\BmpReg.o "
|
||||
"C:/upp0802/out/plugin/png/MINGW.Gui\\pngreg.o "
|
||||
"--start-group "
|
||||
"C:/upp0802/out/CtrlLib/MINGW.Gui\\CtrlLib.a "
|
||||
"-ladvapi32 "
|
||||
"-lcomdlg32 "
|
||||
"-lcomctl32 "
|
||||
"C:/upp0802/out/CtrlCore/MINGW.Gui\\CtrlCore.a "
|
||||
"C:/upp0802/out/RichText/MINGW.Gui\\RichText.a "
|
||||
"-luser32 "
|
||||
"-lgdi32 "
|
||||
"C:/upp0802/out/Draw/MINGW.Gui\\Draw.a "
|
||||
"C:/upp0802/out/plugin/bmp/MINGW.Gui\\bmp.a "
|
||||
"-ladvapi32 "
|
||||
"-lshell32 "
|
||||
"-lwinmm "
|
||||
"-lmpr "
|
||||
"-lole32 "
|
||||
"-loleaut32 "
|
||||
"-luuid "
|
||||
"C:/upp0802/out/Core/MINGW.Gui\\Core.a "
|
||||
"C:/upp0802/out/plugin/z/MINGW.Gui\\z.a "
|
||||
"C:/upp0802/out/plugin/png/MINGW.Gui\\png.a "
|
||||
"--end-group "
|
||||
"-lstdc++ "
|
||||
"-lmingw32 "
|
||||
"-lgcc "
|
||||
"-lmoldname "
|
||||
"-lmingwex "
|
||||
"-lmsvcrt "
|
||||
"-lgdi32 "
|
||||
"-lcomdlg32 "
|
||||
"-luser32 "
|
||||
"-lkernel32 "
|
||||
"-ladvapi32 "
|
||||
"-lshell32 "
|
||||
"-lmingw32 "
|
||||
"-lgcc "
|
||||
"-lmoldname "
|
||||
"-lmingwex "
|
||||
"-lmsvcrt "
|
||||
"c:/upp0802/mingw/bin/../lib/gcc/mingw32/4.3.0/crtend.o "
|
||||
|
||||
, true);
|
||||
linkjob.Link();
|
||||
#endif
|
||||
}
|
||||
|
||||
CONSOLE_APP_MAIN
|
||||
{
|
||||
/*
|
||||
{
|
||||
RTIMING("VectorMap");
|
||||
VectorMap<int, int> temp;
|
||||
for(int i = 0; i < 1000000; i++)
|
||||
temp.Add(i, -1);
|
||||
}
|
||||
*/
|
||||
|
||||
// static void *hovno;
|
||||
// __asm int 3
|
||||
// __asm jmp [hovno]
|
||||
|
||||
// PutConsole("ULD::Main");
|
||||
|
||||
try
|
||||
{
|
||||
TryMain();
|
||||
}
|
||||
catch(Exc e)
|
||||
{
|
||||
PutStdOut(e);
|
||||
SetExitCode(1);
|
||||
}
|
||||
}
|
||||
16
uppsrc2/coff/uld/notes.txt
Normal file
16
uppsrc2/coff/uld/notes.txt
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
padani inicializace
|
||||
|
||||
* ? zarovnat raw data size u segmentu text / data / bss (v hlavicce je vetsi nez v section headeru)
|
||||
|
||||
* ? relokacni informace je cca 1.5 x delsi u ULD
|
||||
|
||||
* ? export section je o 8 bytu delsi u ULD
|
||||
|
||||
* ? reloc section je u ULD DISCARDABLE + READ, u LD je READ + WRITE
|
||||
navic u LD je pred STABy, u ULD za STABy
|
||||
|
||||
* ? importy u LD jsou serazene podle ordinalu
|
||||
|
||||
* ? exporty u LD jsou serazene podle abecedy
|
||||
|
||||
spojovat templaty
|
||||
564
uppsrc2/coff/uld/obj.h
Normal file
564
uppsrc2/coff/uld/obj.h
Normal file
|
|
@ -0,0 +1,564 @@
|
|||
#ifndef _console_uld_obj_h_
|
||||
#define _console_uld_obj_h_
|
||||
|
||||
static inline int CoffSectionAlignShift(int flags)
|
||||
{
|
||||
int v = (flags >> 20) & 15;
|
||||
return v ? v - 1 : 2;
|
||||
}
|
||||
|
||||
static inline int CoffGetLengthAlignment(int align, int length)
|
||||
{
|
||||
/*
|
||||
for(int i = 1; i < align; i <<= 1)
|
||||
if(length & i)
|
||||
return i;
|
||||
*/
|
||||
return align;
|
||||
}
|
||||
|
||||
typedef int atom_t;
|
||||
|
||||
class LinkJob;
|
||||
|
||||
class ObjSec : Moveable<ObjSec>
|
||||
{
|
||||
public:
|
||||
ObjSec() {}
|
||||
ObjSec(const Nuller& nuller) : object(-1), section(0) {}
|
||||
ObjSec(int object, int section) : object(object), section(section) {}
|
||||
|
||||
unsigned GetHashValue() const { return CombineHash(::GetHashValue(object), ::GetHashValue(section)); }
|
||||
bool IsNullInstance() const { return object < 0; }
|
||||
|
||||
public:
|
||||
int object;
|
||||
int section;
|
||||
};
|
||||
|
||||
inline bool operator == (const ObjSec& a, const ObjSec& b) { return a.object == b.object && a.section == b.section; }
|
||||
inline bool operator != (const ObjSec& a, const ObjSec& b) { return !(a == b); }
|
||||
|
||||
namespace Upp {
|
||||
NTL_MOVEABLE(COFF_IMAGE_SYMBOL)
|
||||
};
|
||||
|
||||
class ObjectFile
|
||||
{
|
||||
public:
|
||||
enum FILETYPE { DIRECT, FULL_PATH, LIB_PATH, DEFAULTLIB, INTERNAL, };
|
||||
ObjectFile(LinkJob& job, int index, String library_file, String object_file,
|
||||
FILETYPE filetype, int library_offset, Time file_time, int object_size);
|
||||
|
||||
void ReadFile(const byte *mapping);
|
||||
String ToString() const;
|
||||
|
||||
void Dump() const;
|
||||
|
||||
public:
|
||||
enum SEC_TYPE { SEC_ANON_COMDAT, SEC_STD, SEC_STAB, SEC_STABSTR, /*SEC_INULL,*/ SEC_RAW, SEC_DEBUG };
|
||||
enum COM_STATE { COM_UNK, COM_SELECTED, COM_TRASHED };
|
||||
|
||||
struct Section
|
||||
{
|
||||
Section() : name_atom(0), sec_atom(0), size(0), raw_size(0), offset(0), flags(0)
|
||||
, ref_sec_index(0), ref_ext_index(0), sec_map_index(-1) /*, comdat_forward(-1)*/
|
||||
, used(false), autocollect(false), comdat_state(COM_UNK), type(SEC_RAW), comdat_packing(0) {}
|
||||
|
||||
int name_atom;
|
||||
int sec_atom;
|
||||
int size;
|
||||
int raw_size;
|
||||
int offset;
|
||||
int flags;
|
||||
int ref_sec_index;
|
||||
int ref_ext_index;
|
||||
int sec_map_index;
|
||||
// int comdat_forward;
|
||||
Vector<byte> section_data;
|
||||
bool autocollect;
|
||||
bool used;
|
||||
COM_STATE comdat_state;
|
||||
SEC_TYPE type;
|
||||
char comdat_packing;
|
||||
};
|
||||
|
||||
struct Import
|
||||
{
|
||||
Import() : app_atom(0), imp_atom(0), ordinal_hint(0) {}
|
||||
|
||||
int app_atom;
|
||||
int imp_atom;
|
||||
int ordinal_hint;
|
||||
};
|
||||
|
||||
public:
|
||||
LinkJob& linkjob;
|
||||
int index;
|
||||
int archive_index;
|
||||
String library_file;
|
||||
String object_file;
|
||||
Time file_time;
|
||||
int object_size;
|
||||
String object_data;
|
||||
int library_offset;
|
||||
int dll_atom;
|
||||
int stab_index;
|
||||
int stabstr_index;
|
||||
FILETYPE filetype;
|
||||
bool used_any;
|
||||
bool collected;
|
||||
bool has_ctors_dtors;
|
||||
bool export_symbols;
|
||||
// String directives;
|
||||
Vector<int> ref_sections;
|
||||
Vector<int> ref_externals;
|
||||
Array<Section> sections;
|
||||
Array<Import> imports;
|
||||
Index<int> used_stubs;
|
||||
Index<int> used_imports;
|
||||
enum
|
||||
{
|
||||
SEC_COMDAT,
|
||||
SEC_DLL_STUBS,
|
||||
SEC_DLL_NAMES,
|
||||
SEC_DLL_IMPORTS,
|
||||
SEC_DLL_BOUND,
|
||||
SEC_DLL_DESCRIPTOR,
|
||||
// SEC_DLL_NULL_DESC,
|
||||
DLL_SECTIONS
|
||||
};
|
||||
VectorMap<int, int> comdat_assoc;
|
||||
};
|
||||
|
||||
class LinkJob
|
||||
{
|
||||
public:
|
||||
enum
|
||||
{
|
||||
COFF_IMAGE_SYM_TYPE_SPECIAL = 0xFF00,
|
||||
COFF_IMAGE_SYM_TYPE_SECTION,
|
||||
COFF_IMAGE_SYM_TYPE_IMPORT_NAME,
|
||||
COFF_IMAGE_SYM_TYPE_IMPORT_ORDINAL,
|
||||
COFF_IMAGE_SYM_TYPE_IMPORT_STUB,
|
||||
COFF_IMAGE_SYM_TYPE_BASE,
|
||||
COFF_IMAGE_SYM_TYPE_CTOR_DTOR,
|
||||
};
|
||||
enum SPECIAL_OBJECTS
|
||||
{
|
||||
OBJ_MARKER,
|
||||
OBJ_CTOR,
|
||||
OBJ_EXPORT,
|
||||
OBJ_FIRST, // first user object
|
||||
};
|
||||
enum
|
||||
{
|
||||
OBJM_COMDAT,
|
||||
OBJM_DATA_BEGIN,
|
||||
OBJM_PSEUDO_RELOC_BEGIN,
|
||||
OBJM_PSEUDO_RELOC_END,
|
||||
OBJM_BSS_BEGIN,
|
||||
OBJM_BSS_END,
|
||||
OBJM_COUNT,
|
||||
};
|
||||
enum
|
||||
{
|
||||
OBJC_COMDAT,
|
||||
OBJC_CTOR_BEGIN,
|
||||
OBJC_CTOR_END,
|
||||
OBJC_DTOR_BEGIN,
|
||||
OBJC_DTOR_END,
|
||||
OBJC_IDATA_HOLE,
|
||||
OBJC_IDATA_NULL,
|
||||
OBJC_COUNT
|
||||
};
|
||||
enum
|
||||
{
|
||||
OBJE_COMDAT,
|
||||
OBJE_DIRECTORY,
|
||||
OBJE_ADDRESS_TABLE,
|
||||
OBJE_NAME_POINTERS,
|
||||
OBJE_ORDINALS,
|
||||
OBJE_NAMES,
|
||||
OBJE_COUNT,
|
||||
};
|
||||
|
||||
struct Symbol
|
||||
{
|
||||
Symbol(ObjSec obj_sec = Null, int value = 0, word type = 0, bool external = false)
|
||||
: obj_sec(obj_sec), value(value), type(type)
|
||||
, linked(false), used(false), relocated(false), external(external) {}
|
||||
|
||||
ObjSec obj_sec;
|
||||
int value;
|
||||
word type;
|
||||
bool linked : 1;
|
||||
bool used : 1;
|
||||
bool relocated : 1;
|
||||
bool external : 1;
|
||||
|
||||
String ToString() const;
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
GRP_CODE,
|
||||
GRP_RDATA,
|
||||
GRP_DATA,
|
||||
GRP_UDATA,
|
||||
GRP_EDATA,
|
||||
GRP_IDATA,
|
||||
GRP_RSRC,
|
||||
GRP_DEBUG,
|
||||
GRP_STAB,
|
||||
GRP_STABSTR,
|
||||
GRP_SYMBOLS,
|
||||
GRP_COUNT,
|
||||
|
||||
GRP_NONE = -1,
|
||||
GRP_TEXT_BEGIN = GRP_CODE,
|
||||
GRP_DATA_BEGIN = GRP_RDATA,
|
||||
GRP_BSS_BEGIN = GRP_UDATA,
|
||||
GRP_BSS_END = GRP_UDATA + 1,
|
||||
};
|
||||
|
||||
static String GetGroupName(int group_id);
|
||||
|
||||
struct Group
|
||||
{
|
||||
int first_section;
|
||||
int rva;
|
||||
int rfa;
|
||||
int raw_size;
|
||||
};
|
||||
|
||||
struct Section
|
||||
{
|
||||
Section() : obj_sec(Null), udata(false), group(0), app_section(0), sec_atom(0), rva(-1), rfa(-1), size(0) {}
|
||||
|
||||
ObjSec obj_sec;
|
||||
byte group;
|
||||
bool udata;
|
||||
word app_section;
|
||||
String name;
|
||||
int sec_atom;
|
||||
int rva;
|
||||
int rfa;
|
||||
int size;
|
||||
};
|
||||
|
||||
struct Stab
|
||||
{
|
||||
Stab() : textoff(0), type(0), other(0), desc(0), value(0), /*fileatom(0),*/ fixup(Null) {}
|
||||
|
||||
int textoff;
|
||||
byte type;
|
||||
byte other;
|
||||
word desc;
|
||||
int value;
|
||||
// int fileatom;
|
||||
ObjSec fixup;
|
||||
|
||||
// unsigned GetHashValue() const;
|
||||
// bool Equals(const Stab& b) const;
|
||||
|
||||
// friend bool operator == (const Stab& a, const Stab& b) { return a.Equals(b); }
|
||||
// friend bool operator != (const Stab& a, const Stab& b) { return !a.Equals(b); }
|
||||
};
|
||||
|
||||
struct Export
|
||||
{
|
||||
Export(String export_name, int ordinal) : export_name(export_name), ordinal(ordinal) {}
|
||||
|
||||
String export_name;
|
||||
int ordinal;
|
||||
};
|
||||
|
||||
struct Cache
|
||||
{
|
||||
FileMapping mapping;
|
||||
int lock;
|
||||
};
|
||||
|
||||
/*
|
||||
struct Cache
|
||||
{
|
||||
String library;
|
||||
String file;
|
||||
Time time;
|
||||
int offset;
|
||||
int size;
|
||||
|
||||
void Serialize(Stream& stream);
|
||||
};
|
||||
*/
|
||||
|
||||
struct AtomOrder
|
||||
{
|
||||
AtomOrder(const LinkJob& linkjob) : linkjob(linkjob), langinfo(GetLanguageInfo()) {}
|
||||
bool operator () (int a, int b) const { return langinfo(linkjob[a], linkjob[b]); }
|
||||
const LinkJob& linkjob;
|
||||
const LanguageInfo& langinfo;
|
||||
};
|
||||
|
||||
struct GlobalAddressOrder
|
||||
{
|
||||
GlobalAddressOrder(const LinkJob& linkjob) : linkjob(linkjob), langinfo(GetLanguageInfo()) {}
|
||||
bool operator () (int a, int b) const;
|
||||
const LinkJob& linkjob;
|
||||
const LanguageInfo& langinfo;
|
||||
};
|
||||
|
||||
static bool Less(const Section& a, const Section& b);
|
||||
|
||||
public:
|
||||
LinkJob();
|
||||
|
||||
static String Usage();
|
||||
|
||||
void ReadCommand(const Vector<String>& cmdline, bool user);
|
||||
void ReadCommand(const char *cmdline, bool user);
|
||||
void ReadDefaultLibs();
|
||||
|
||||
void Link();
|
||||
|
||||
void LoadFile(String file, bool defaultlib);
|
||||
void LoadObject(String file, const FileMapping& mapping, ObjectFile::FILETYPE filetype);
|
||||
void LoadDLL(String file, const FileMapping& mapping, ObjectFile::FILETYPE filetype);
|
||||
void LoadLibrary(String file, const FileMapping& mapping, ObjectFile::FILETYPE filetype);
|
||||
|
||||
void SetEntryPoint();
|
||||
void SetExportSymbols();
|
||||
void SetRootSymbols();
|
||||
void CollectSymbols();
|
||||
void CollectSectionSymbols(Index<ObjSec>& collect_objsec, int referer_index);
|
||||
void CollectObject(int index);
|
||||
void FixupAnonComdats();
|
||||
// void CheckDuplicates();
|
||||
void CollectImports();
|
||||
void CollectExports();
|
||||
void CollectSections();
|
||||
void PrepareImageHeader();
|
||||
void RelocateGlobals();
|
||||
void RelocateExports();
|
||||
void PrepareImageInfo();
|
||||
void WriteImageFile();
|
||||
// void OpenCacheFile();
|
||||
// void SaveCacheFile();
|
||||
void WriteImageSections();
|
||||
void RelocateImport(const ObjectFile& of);
|
||||
void RelocateObject(const ObjectFile& of, const byte *object_ptr);
|
||||
void RelocateInternal(const ObjectFile& of);
|
||||
void RelocateStabs(const ObjectFile& of, const byte *object_ptr);
|
||||
void CheckUnresolved();
|
||||
void PrepareSymbolTable();
|
||||
void PrepareStabBlocks();
|
||||
void PrepareFixupBlocks();
|
||||
void WriteMapFile();
|
||||
void WriteMapGlobals(String& map, const Vector<int>& used, String name);
|
||||
void BuildLibrary();
|
||||
void BuildDefFiles();
|
||||
|
||||
atom_t Atomize(String atom) { return atoms.FindAdd(atom); }
|
||||
String operator [] (atom_t atom) const { return atoms[atom]; }
|
||||
atom_t NameAtom(const COFF_IMAGE_SYMBOL& isym, const char *strtbl) { return Atomize(COFFSymbolName(isym, strtbl)); }
|
||||
String DemangleAtom(atom_t atom) const;
|
||||
FileMapping& GetMapping(String filename);
|
||||
void LockMapping(String filename);
|
||||
void UnlockMapping(String filename);
|
||||
|
||||
ObjectFile::Section& GetSection(ObjSec os) { return objects[os.object].sections[os.section]; }
|
||||
const ObjectFile::Section& GetSection(ObjSec os) const { return objects[os.object].sections[os.section]; }
|
||||
// const ObjectFile::Section& GetSection0(ObjSec os) const { return objects[os.section ? os.object : 0].sections[os.section]; }
|
||||
String FormatSection(ObjSec os) const;
|
||||
|
||||
void AddExternal(atom_t atom, ObjSec obj_sec) { ext_obj_sec.Add(atom, obj_sec); }
|
||||
void AddWeakExternal(atom_t atom, int refatom);
|
||||
void AddGlobal(atom_t atom, const Symbol& symbol);
|
||||
void AddCollect(atom_t atom) { collected_symbols.FindAdd(atom, -1); }
|
||||
|
||||
bool AddCOFFSymbol(String name, int object, const COFF_IMAGE_SYMBOL& sym);
|
||||
void AddAuxCOFFSymbol(const COFF_IMAGE_SYMBOL& sym);
|
||||
|
||||
void Dump() const;
|
||||
|
||||
public:
|
||||
enum
|
||||
{
|
||||
DUMP_IMPORT_LIBS = 0x00000001,
|
||||
DUMP_OBJECT_LIBS = 0x00000002,
|
||||
DUMP_COLLECTOR = 0x00000004,
|
||||
DUMP_REF_FIXUPS = 0x00000008,
|
||||
DUMP_SECTIONS = 0x00000010,
|
||||
DUMP_SECTIONS_ALL = 0x00000020,
|
||||
DUMP_SEC_DEFINES = 0x00000040,
|
||||
DUMP_STAT = 0x00000080,
|
||||
DUMP_IMPORT = 0x00000100,
|
||||
DUMP_OBJECTS = 0x00000200,
|
||||
DUMP_TIMING = 0x00000400,
|
||||
DUMP_MAP_UNUSED = 0x00000800,
|
||||
DUMP_STABS = 0x00001000,
|
||||
DUMP_STAB_TYPES = 0x00002000,
|
||||
DUMP_MAP_ALL = 0x00004000,
|
||||
DUMP_EXPORTS = 0x00008000,
|
||||
DUMP_DLL_EXPORTS = 0x00010000,
|
||||
DUMP_COMMANDLINE = 0x00020000,
|
||||
DUMP_ENVIRONMENT = 0x00040000,
|
||||
DUMP_COMDAT_REMAPS = 0x00080000,
|
||||
};
|
||||
int dump_flags;
|
||||
Vector<String> libpaths;
|
||||
Index<String> defaultlibs;
|
||||
Index<String> nodefaultlibs;
|
||||
String dll_search_prefix;
|
||||
int subsystem;
|
||||
int machine;
|
||||
String outputfile;
|
||||
String mapfile;
|
||||
bool write_mapfile;
|
||||
bool mapfile_stdout;
|
||||
bool write_xref;
|
||||
signed char debug_info_raw;
|
||||
bool debug_info;
|
||||
bool show_logo;
|
||||
bool autocollect_crt_only;
|
||||
bool ignore_code_alignment;
|
||||
bool static_libraries;
|
||||
bool make_lib;
|
||||
bool make_dll;
|
||||
bool make_def;
|
||||
bool auto_dll_base;
|
||||
// bool cache_objects;
|
||||
bool cache_object_data;
|
||||
bool verbose;
|
||||
word major_version;
|
||||
word minor_version;
|
||||
word major_subsystem_version;
|
||||
word minor_subsystem_version;
|
||||
enum MODE { MODE_MSLINK, MODE_GNULD };
|
||||
MODE linkermode;
|
||||
int file_align;
|
||||
int image_align;
|
||||
int image_base;
|
||||
bool image_fixed;
|
||||
int stack_reserve;
|
||||
int stack_commit;
|
||||
int heap_reserve;
|
||||
int heap_commit;
|
||||
|
||||
Index<String> atoms;
|
||||
atom_t text_atom;
|
||||
atom_t data_atom;
|
||||
atom_t edata_atom;
|
||||
atom_t crt_atom;
|
||||
atom_t ctors_atom;
|
||||
atom_t dtors_atom;
|
||||
atom_t gcc_except_atom;
|
||||
atom_t CTOR_LIST_atom;
|
||||
atom_t _CTOR_LIST_atom;
|
||||
atom_t CTOR_LIST_END_atom;
|
||||
atom_t DTOR_LIST_atom;
|
||||
atom_t _DTOR_LIST_atom;
|
||||
atom_t DTOR_LIST_END_atom;
|
||||
atom_t idata_atom;
|
||||
atom_t idata_idesc_atom;
|
||||
atom_t idata_inull_atom;
|
||||
atom_t idata_iat1_atom;
|
||||
atom_t idata_iat2_atom;
|
||||
atom_t idata_names_atom;
|
||||
atom_t rdata_atom;
|
||||
atom_t bss_atom;
|
||||
atom_t debug_atom;
|
||||
atom_t drectve_atom;
|
||||
atom_t stab_atom;
|
||||
atom_t stabstr_atom;
|
||||
atom_t rsrc_atom;
|
||||
// int mangling_style;
|
||||
|
||||
enum {
|
||||
I386_IMP_STUB_SIZE = 6,
|
||||
ARM_IMP_STUB_SIZE = 12,
|
||||
I386_IMP_ENTRY_SIZE = 4,
|
||||
ARM_IMP_ENTRY_SIZE = 4,
|
||||
};
|
||||
|
||||
// Array<Cache> object_cache;
|
||||
// Index<String> cache_name_index;
|
||||
// Index<String> cache_library_index;
|
||||
// FileStream cache_file;
|
||||
// String cache_file_name;
|
||||
// bool cache_dirty;
|
||||
|
||||
Vector<String> command_args;
|
||||
Vector<String> user_command_args;
|
||||
Vector<String> files_to_load;
|
||||
Index<String> loaded_files;
|
||||
Array<ObjectFile> objects;
|
||||
VectorMap<atom_t, int> dll_objects; // dll name -> index into objects
|
||||
Vector<atom_t> used_dll_objects;
|
||||
int stab_section;
|
||||
int stabstr_section;
|
||||
int symbol_section;
|
||||
int reloc_section;
|
||||
int section_count;
|
||||
bool has_stabs;
|
||||
// bool has_symbols;
|
||||
// bool has_relocs;
|
||||
|
||||
String entrypoint;
|
||||
atom_t entrypoint_atom;
|
||||
VectorMap<atom_t, int> collected_symbols;
|
||||
VectorMap<atom_t, Index<atom_t> > collected_referer;
|
||||
VectorMap<atom_t, atom_t> weak_externals;
|
||||
VectorMap<atom_t, atom_t> section_merge;
|
||||
ArrayMap<atom_t, Symbol> globals;
|
||||
Index<ObjSec> global_obj_sec_index;
|
||||
VectorMap<Point, int> obj_static_global_index;
|
||||
VectorMap<atom_t, ObjSec> ext_obj_sec;
|
||||
|
||||
ArrayMap<String, Cache> mapping_cache;
|
||||
int mapping_cache_limit;
|
||||
|
||||
Segtor<Section, 256> section_map;
|
||||
Index<int> section_object_index;
|
||||
// Index<ObjSec> section_obj_sec_index;
|
||||
VectorMap<atom_t, int> section_name_map; // atom -> sec_map_index
|
||||
Group groups[GRP_COUNT + 1];
|
||||
Index<atom_t> unresolved;
|
||||
|
||||
Vector<COFF_IMAGE_SYMBOL> coff_output_symbols;
|
||||
String coff_output_symbol_strings;
|
||||
// Vector<int> coff_reloc_offsets;
|
||||
|
||||
SegtorMap<atom_t, Export, 256> exports;
|
||||
|
||||
Vector<byte> output_image;
|
||||
Vector<byte> output_fixups;
|
||||
int output_fixup_size;
|
||||
VectorMap<String, int> stab_bincl_map;
|
||||
Vector<byte> output_stab_info;
|
||||
Vector<char> output_stab_strings;
|
||||
VectorMap<unsigned, int> output_stab_string_hash;
|
||||
Vector<int> highlow_fixup_rva;
|
||||
time_t timestamp;
|
||||
int ifhdr_pos;
|
||||
int iohdr_pos;
|
||||
int secmap_pos;
|
||||
int header_size;
|
||||
int code_rva;
|
||||
int code_rfa;
|
||||
int idesc_rva;
|
||||
int idesc_end_rva;
|
||||
int rsrc_rva;
|
||||
int rsrc_end_rva;
|
||||
int iat2_rva;
|
||||
int iat2_end_rva;
|
||||
int idata_last;
|
||||
bool idata_null_found;
|
||||
int start_time;
|
||||
String stub_filename;
|
||||
int imp_stub_size;
|
||||
int imp_entry_size;
|
||||
};
|
||||
|
||||
#endif//_console_uld_obj_h_
|
||||
396
uppsrc2/coff/uld/object.cpp
Normal file
396
uppsrc2/coff/uld/object.cpp
Normal file
|
|
@ -0,0 +1,396 @@
|
|||
#include "uld.h"
|
||||
#pragma hdrstop
|
||||
|
||||
#include "obj.h"
|
||||
|
||||
#define LTIMING(x) // RTIMING(x)
|
||||
#define LDUMP(x) // RDUMP(x)
|
||||
|
||||
/*
|
||||
static inline unsigned MemHash(const char *b, const char *p)
|
||||
{
|
||||
unsigned out = p - b;
|
||||
while(p - b >= 4)
|
||||
{
|
||||
out ^= PeekIL(b);
|
||||
b += 4;
|
||||
}
|
||||
switch(p - b)
|
||||
{
|
||||
case 3: out ^= byte(b[2]) << 16;
|
||||
case 2: out ^= byte(b[1]) << 8;
|
||||
case 1: out ^= byte(b[0]) << 0;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static inline Point ScanStabType(const char *p, const char *& endptr)
|
||||
{
|
||||
ASSERT(*p == '(' && IsDigit(p[1]));
|
||||
Point out(0, 0);
|
||||
while(IsDigit(*++p))
|
||||
out.x = 10 * out.x + *p - '0';
|
||||
if(*p == ',')
|
||||
while(IsDigit(*++p))
|
||||
out.y = 10 * out.y + *p - '0';
|
||||
if(*p == ')')
|
||||
p++;
|
||||
endptr = p;
|
||||
return out;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static inline const char *ScanStab(const char *p)
|
||||
{
|
||||
if(*p == '(')
|
||||
while(*p && *p++ != ')')
|
||||
;
|
||||
else if(IsDigit(*p))
|
||||
while(IsDigit(*++p))
|
||||
;
|
||||
return p;
|
||||
}
|
||||
*/
|
||||
|
||||
static inline String TrimClassName(String clss)
|
||||
{
|
||||
int f = clss.Find('$');
|
||||
if(f >= 0)
|
||||
clss.Trim(f);
|
||||
return clss;
|
||||
}
|
||||
|
||||
static String Undecorate(String s)
|
||||
{
|
||||
const char *p = s;
|
||||
while(*p && *p != '$')
|
||||
p++;
|
||||
if(*p != '$')
|
||||
return s;
|
||||
const char *b = ++p;
|
||||
while(*p && *p != '@')
|
||||
p++;
|
||||
return String(b, p);
|
||||
}
|
||||
|
||||
ObjectFile::ObjectFile(LinkJob& j, int i, String lf, String of, FILETYPE ft, int lo, Time tm, int os)
|
||||
: linkjob(j), index(i), library_file(lf), object_file(of)
|
||||
, filetype(ft), library_offset(lo), file_time(tm), object_size(os)
|
||||
{
|
||||
archive_index = -1;
|
||||
collected = used_any = false;
|
||||
dll_atom = 0;
|
||||
stab_index = -1;
|
||||
stabstr_index = -1;
|
||||
has_ctors_dtors = false;
|
||||
//!! terrible kludge
|
||||
String title = ToLower(GetFileTitle(object_file));
|
||||
export_symbols = (filetype == DIRECT && title != "dllcrt2" && title != "crtbegin");
|
||||
}
|
||||
|
||||
String ObjectFile::ToString() const
|
||||
{
|
||||
if(IsNull(library_file))
|
||||
{
|
||||
if(IsNull(object_file))
|
||||
return "(linker)";
|
||||
return object_file;
|
||||
}
|
||||
return GetFileName(library_file) + ":" + object_file;
|
||||
}
|
||||
|
||||
void ObjectFile::ReadFile(const byte *begin)
|
||||
{
|
||||
const COFF_IMAGE_FILE_HEADER *header = (const COFF_IMAGE_FILE_HEADER *)begin;
|
||||
|
||||
int i;
|
||||
/*
|
||||
const COFF_IMAGE_SYMBOL *symtbl = (const COFF_IMAGE_SYMBOL *)(begin + header->PointerToSymbolTable);
|
||||
int nsym = header->NumberOfSymbols;
|
||||
const COFF_IMAGE_SYMBOL *symend = symtbl + nsym;
|
||||
const char *strtbl = (const char *)symend;
|
||||
symbols.Reserve(nsym);
|
||||
while(symtbl < symend)
|
||||
{
|
||||
String name;
|
||||
if(symtbl->N.Name.Short)
|
||||
name = MaxLenString(symtbl->N.ShortName, 8);
|
||||
else
|
||||
name = strtbl + symtbl->N.Name.Long;
|
||||
int atom = linkjob.Atomize(name);
|
||||
int naux = symtbl->NumberOfAuxSymbols;
|
||||
symbols.Add(atom, *symtbl++);
|
||||
while(--naux >= 0)
|
||||
symbols.Add(0, *symtbl++);
|
||||
}
|
||||
*/
|
||||
const COFF_IMAGE_SECTION_HEADER *sechdr = (const COFF_IMAGE_SECTION_HEADER *)(begin
|
||||
+ sizeof(COFF_IMAGE_FILE_HEADER) + header->SizeOfOptionalHeader), *secptr;
|
||||
sections.SetCount(header->NumberOfSections + 1);
|
||||
Section& comdat = sections[0];
|
||||
comdat.type = SEC_ANON_COMDAT;
|
||||
comdat.name_atom = comdat.sec_atom = linkjob.bss_atom;
|
||||
comdat.flags = COFF_IMAGE_SCN_CNT_UNINITIALIZED_DATA | COFF_IMAGE_SCN_ALIGN_16BYTES
|
||||
| COFF_IMAGE_SCN_MEM_READ | COFF_IMAGE_SCN_MEM_WRITE;
|
||||
comdat.comdat_packing = 0;
|
||||
for(i = 1, secptr = sechdr; i < sections.GetCount(); i++, secptr++) {
|
||||
Section& sec = sections[i];
|
||||
sec.size = sec.raw_size = max(secptr->SizeOfRawData, secptr->Misc.VirtualSize);
|
||||
// if(!(sec.size = secptr->Misc.VirtualSize))
|
||||
// sec.size = sec.raw_size;
|
||||
sec.offset = secptr->PointerToRawData;
|
||||
ASSERT(sec.offset >= 0);
|
||||
sec.flags = secptr->Characteristics;
|
||||
sec.comdat_packing = 0;
|
||||
// sec.comdat_assoc = 0;
|
||||
|
||||
String secn = MaxLenString(secptr->Name, sizeof(secptr->Name));
|
||||
if(secn[0] != '.') {
|
||||
if(sec.flags & COFF_IMAGE_SCN_CNT_CODE)
|
||||
secn = ".text$" + secn;
|
||||
else if(sec.flags & COFF_IMAGE_SCN_CNT_INITIALIZED_DATA)
|
||||
secn = ".data$" + secn;
|
||||
else
|
||||
secn = ".bss$" + secn;
|
||||
}
|
||||
sec.name_atom = linkjob.Atomize(secn);
|
||||
secn = TrimClassName(secn);
|
||||
sec.sec_atom = linkjob.Atomize(secn);
|
||||
bool ctor_dtor_section = false;
|
||||
if(sec.sec_atom == linkjob.ctors_atom || sec.sec_atom == linkjob.dtors_atom) {
|
||||
sec.sec_atom = linkjob.data_atom;
|
||||
// sec.flags = (sec.flags & ~COFF_IMAGE_SCN_ALIGN_MASK) | COFF_IMAGE_SCN_ALIGN_4BYTES;
|
||||
has_ctors_dtors = ctor_dtor_section = true;
|
||||
}
|
||||
if(sec.sec_atom == linkjob.idata_atom)
|
||||
linkjob.idata_last = index;
|
||||
if(sec.name_atom == linkjob.idata_inull_atom)
|
||||
linkjob.idata_null_found = true;
|
||||
|
||||
sec.type = (sec.sec_atom == linkjob.stab_atom
|
||||
? SEC_STAB : sec.sec_atom == linkjob.stabstr_atom
|
||||
? SEC_STABSTR : sec.sec_atom == linkjob.debug_atom
|
||||
? SEC_DEBUG : SEC_STD);
|
||||
if(sec.type == SEC_STAB)
|
||||
stab_index = i;
|
||||
else if(sec.type == SEC_STABSTR)
|
||||
stabstr_index = i;
|
||||
sec.autocollect = sec.type == SEC_STD
|
||||
&& (sec.sec_atom == linkjob.crt_atom
|
||||
|| ctor_dtor_section
|
||||
|| sec.sec_atom == linkjob.idata_atom
|
||||
|| sec.sec_atom == linkjob.rsrc_atom
|
||||
|| !linkjob.autocollect_crt_only && (sec.flags & COFF_IMAGE_SCN_CNT_INITIALIZED_DATA));
|
||||
if(sec.name_atom == linkjob.drectve_atom && (sec.flags & COFF_IMAGE_SCN_LNK_INFO))
|
||||
{
|
||||
String directives = String(begin + secptr->PointerToRawData, secptr->SizeOfRawData);
|
||||
linkjob.ReadCommand(directives, false);
|
||||
}
|
||||
|
||||
if(sec.flags & COFF_IMAGE_SCN_CNT_CODE)
|
||||
sec.sec_atom = linkjob.text_atom;
|
||||
}
|
||||
|
||||
if(stab_index >= 0 && stabstr_index >= 0)
|
||||
linkjob.has_stabs = true;
|
||||
|
||||
const COFF_IMAGE_SYMBOL *symtbl = (const COFF_IMAGE_SYMBOL *)(begin + header->PointerToSymbolTable), *symptr = symtbl;
|
||||
const char *strtbl = (const char *)(symtbl + header->NumberOfSymbols);
|
||||
// int xxxatom = linkjob.Atomize("?AppMain@@YAXXZ");
|
||||
for(i = 0; i < (int)header->NumberOfSymbols; i++, symptr++)
|
||||
{
|
||||
// if(symptr->SectionNumber > 0 && linkjob.NameAtom(*symptr, strtbl) == xxxatom)
|
||||
// __asm int 3;
|
||||
// RLOG(NFormat("%30<s SEC %04d VAL %08x %s", linkjob[linkjob.NameAtom(*symptr, strtbl)],
|
||||
// symptr->SectionNumber, (int)symptr->Value, file));
|
||||
|
||||
if(symptr->StorageClass == COFF_IMAGE_SYM_CLASS_STATIC && symptr->SectionNumber != 0
|
||||
&& symptr->Value == 0 && symptr->NumberOfAuxSymbols >= 1)
|
||||
// && linkjob.Atomize(TrimClassName(COFFSymbolName(*symptr, strtbl))) == sections[(int)symptr->SectionNumber].name_atom)
|
||||
{ // section aux symbol
|
||||
LinkJob::Symbol lsym;
|
||||
lsym.obj_sec.object = index;
|
||||
lsym.obj_sec.section = symptr->SectionNumber;
|
||||
lsym.value = 0;
|
||||
lsym.type = LinkJob::COFF_IMAGE_SYM_TYPE_SECTION;
|
||||
Section& sec = sections[(int)symptr->SectionNumber];
|
||||
if(sec.name_atom != linkjob.ctors_atom && sec.name_atom != linkjob.dtors_atom) {
|
||||
String secn = COFFSymbolName(*symptr, strtbl);
|
||||
sec.name_atom = linkjob.Atomize(secn);
|
||||
if(sec.flags & COFF_IMAGE_SCN_CNT_CODE)
|
||||
sec.sec_atom = linkjob.text_atom;
|
||||
else {
|
||||
secn = TrimClassName(secn);
|
||||
sec.sec_atom = linkjob.Atomize(secn);
|
||||
}
|
||||
}
|
||||
linkjob.AddGlobal(sec.name_atom, lsym);
|
||||
const COFF_IMAGE_AUX_SYMBOL *aux = (const COFF_IMAGE_AUX_SYMBOL *)(symptr + 1);
|
||||
if(sec.flags & COFF_IMAGE_SCN_LNK_COMDAT)
|
||||
{
|
||||
sec.comdat_packing = aux->Section.Selection;
|
||||
comdat_assoc.Add(aux->Section.Number, symptr->SectionNumber);
|
||||
// sec.comdat_assoc = aux->Section.Number;
|
||||
if(sec.comdat_packing == COFF_IMAGE_COMDAT_SELECT_EXACT_MATCH)
|
||||
{
|
||||
secptr = sechdr + (symptr->SectionNumber);
|
||||
sec.section_data.Reserve(secptr->SizeOfRawData + secptr->NumberOfRelocations * sizeof(COFF_IMAGE_RELOCATION));
|
||||
CatN(sec.section_data, secptr->SizeOfRawData, begin + secptr->PointerToRawData);
|
||||
const COFF_IMAGE_RELOCATION *relptr = (const COFF_IMAGE_RELOCATION *)(begin + secptr->PointerToRelocations);
|
||||
const COFF_IMAGE_RELOCATION *relend = relptr + secptr->NumberOfRelocations;
|
||||
while(relptr < relend)
|
||||
{
|
||||
COFF_IMAGE_RELOCATION r = *relptr++;
|
||||
r.SymbolTableIndex = linkjob.NameAtom(symtbl[r.SymbolTableIndex], strtbl);
|
||||
CatN(sec.section_data, sizeof(COFF_IMAGE_RELOCATION), &r);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if((symptr->StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL || symptr->StorageClass == COFF_IMAGE_SYM_CLASS_STATIC)
|
||||
&& (symptr->SectionNumber != 0 || symptr->Value != 0))
|
||||
{
|
||||
LinkJob::Symbol lsym;
|
||||
lsym.obj_sec.object = index;
|
||||
lsym.obj_sec.section = symptr->SectionNumber;
|
||||
lsym.value = symptr->Value;
|
||||
lsym.type = symptr->Type;
|
||||
lsym.external = (symptr->StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL);
|
||||
int atom = linkjob.NameAtom(*symptr, strtbl);
|
||||
linkjob.AddGlobal(atom, lsym);
|
||||
}
|
||||
else if(symptr->StorageClass == COFF_IMAGE_SYM_CLASS_WEAK_EXTERNAL && symptr->NumberOfAuxSymbols >= 1)
|
||||
{
|
||||
int refsym = symptr[1].N.Name.Short;
|
||||
linkjob.AddWeakExternal(linkjob.NameAtom(*symptr, strtbl), linkjob.NameAtom(symtbl[refsym], strtbl));
|
||||
}
|
||||
i += symptr->NumberOfAuxSymbols;
|
||||
symptr += symptr->NumberOfAuxSymbols;
|
||||
}
|
||||
|
||||
for(i = 1, secptr = sechdr; i < sections.GetCount(); i++, secptr++)
|
||||
{
|
||||
Section& sec = sections[i];
|
||||
sec.ref_sec_index = ref_sections.GetCount();
|
||||
sec.ref_ext_index = ref_externals.GetCount();
|
||||
const COFF_IMAGE_RELOCATION *reloc = (const COFF_IMAGE_RELOCATION *)(begin + secptr->PointerToRelocations);
|
||||
if(sec.type == SEC_STD)
|
||||
{
|
||||
Index<int> ref_sec, ref_ext;
|
||||
for(int nreloc = secptr->NumberOfRelocations; --nreloc >= 0; reloc++)
|
||||
{
|
||||
const COFF_IMAGE_SYMBOL& sym = symtbl[reloc->SymbolTableIndex];
|
||||
if(sym.SectionNumber > 0 && sym.StorageClass != COFF_IMAGE_SYM_CLASS_EXTERNAL)
|
||||
ref_sec.FindAdd(sym.SectionNumber);
|
||||
if(sym.StorageClass == COFF_IMAGE_SYM_CLASS_STATIC && sym.SectionNumber > 0
|
||||
&& sym.Value == 0 && sym.NumberOfAuxSymbols >= 1 && !(sections[sym.SectionNumber].flags & COFF_IMAGE_SCN_LNK_COMDAT))
|
||||
{} // no-op for section externals
|
||||
else if(sym.StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL
|
||||
|| sym.StorageClass == COFF_IMAGE_SYM_CLASS_STATIC
|
||||
|| sym.StorageClass == COFF_IMAGE_SYM_CLASS_WEAK_EXTERNAL)
|
||||
{
|
||||
int atom = linkjob.NameAtom(sym, strtbl);
|
||||
if(sym.SectionNumber == 0)
|
||||
linkjob.AddExternal(atom, ObjSec(index, i));
|
||||
ref_ext.FindAdd(atom);
|
||||
}
|
||||
/*
|
||||
{
|
||||
LinkJob::Symbol symbol;
|
||||
symbol.object = index;
|
||||
symbol.value = sym.Value;
|
||||
symbol.type = sym.Type;
|
||||
symbol.section = sym.SectionNumber;
|
||||
ref_ext.FindAdd(linkjob.AddGlobal(linkjob.NameAtom(sym, strtbl), symbol));
|
||||
}
|
||||
*/
|
||||
}
|
||||
ref_sections.AppendPick(ref_sec.PickKeys());
|
||||
ref_externals.AppendPick(ref_ext.PickKeys());
|
||||
}
|
||||
/*
|
||||
else if(sec.type == SEC_STAB && stabstr_index >= 0)
|
||||
{
|
||||
ASSERT(sizeof(STAB_INFO) == 12);
|
||||
int count = sec.size / sizeof(STAB_INFO);
|
||||
stabs.SetCount(count);
|
||||
const byte *p = begin + sec.offset;
|
||||
#ifdef CPU_LE // && CPU_32BIT
|
||||
memcpy(stabs.Begin(), p, count * sizeof(STAB_INFO));
|
||||
#else
|
||||
for(STAB_INFO *sp = stabs.Begin(), *se = stabs.End(); sp < se; sp++, p += 12)
|
||||
{
|
||||
sp->strdx = PeekIL(p + STAB_STRDXOFF);
|
||||
sp->type = p[STAB_TYPEOFF];
|
||||
sp->other = p[STAB_OTHEROFF];
|
||||
sp->desc = PeekIW(p[STAB_DESCOFF]);
|
||||
sp->value = PeekIL(p[STAB_VALUEOFF]);
|
||||
}
|
||||
#endif
|
||||
stab_ref.SetCount(count, 0);
|
||||
for(int nreloc = secptr->NumberOfRelocations; --nreloc >= 0; reloc++)
|
||||
{
|
||||
int entry = reloc->VirtualAddress / sizeof(STAB_INFO);
|
||||
if(entry < 0 || entry >= count)
|
||||
continue;
|
||||
const COFF_IMAGE_SYMBOL& sym = symtbl[reloc->SymbolTableIndex];
|
||||
if(sym.SectionNumber)
|
||||
stab_ref[entry] = ~sym.SectionNumber;
|
||||
else if(sym.StorageClass == COFF_IMAGE_SYM_CLASS_EXTERNAL || sym.StorageClass == COFF_IMAGE_SYM_CLASS_STATIC)
|
||||
stab_ref[entry] = linkjob.NameAtom(sym, strtbl);
|
||||
}
|
||||
if(linkjob.dump_flags & LinkJob::DUMP_STABS)
|
||||
{
|
||||
const Section& strsec = sections[stabstr_index];
|
||||
puts(NFormat("%s: %d stabs, .stab = %d bytes, .stabstr = %d bytes",
|
||||
ToString(), count, sec.size, strsec.size));
|
||||
const byte *str = begin + strsec.offset;
|
||||
for(int i = 0; i < stabs.GetCount(); i++)
|
||||
{
|
||||
const STAB_INFO& stab = stabs[i];
|
||||
String desc;
|
||||
desc << NFormat("[%d]: offset %08x, type %02x, desc %04x, value %08x, reloc %08x",
|
||||
i, stab.strdx, stab.type, stab.desc, stab.value, stab_ref[i]);
|
||||
puts(desc);
|
||||
if(stab.strdx)
|
||||
puts((const char *)(str + stab.strdx));
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
ref_sections.Shrink();
|
||||
ref_externals.Shrink();
|
||||
}
|
||||
|
||||
void ObjectFile::Dump() const
|
||||
{
|
||||
int sym_size = (ref_sections.GetCount() + ref_externals.GetCount()) * sizeof(int);
|
||||
int sec_size = sections.GetCount() * sizeof(Section);
|
||||
int mapped_size = sizeof(ObjectFile) + sym_size + sec_size;
|
||||
|
||||
RLOG("ObjectFile(" << library_file << ":" << object_file << "), mapped size = " << mapped_size
|
||||
<< " (" << sym_size << " in symbols, " << sec_size << " in sections)");
|
||||
// RLOG("Linker directives: " << directives);
|
||||
RLOG("#sections = " << sections.GetCount());
|
||||
/*
|
||||
for(int i = 0; i < sections.GetCount(); i++)
|
||||
{
|
||||
const Section& sec = sections[i];
|
||||
RLOG(NFormat("[%d]: %s", i, linkjob[sec.name_atom]));
|
||||
int end_ext = (i + 1 < sections.GetCount() ? sections[i + 1].ref_ext_index : ref_externals.GetCount());
|
||||
int end_sec = (i + 1 < sections.GetCount() ? sections[i + 1].ref_sec_index : ref_sections.GetCount());
|
||||
RLOG("#external references = " << (end_ext - sec.ref_ext_index));
|
||||
int r;
|
||||
for(r = sec.ref_ext_index; r < end_ext; r++)
|
||||
RLOG(linkjob[linkjob.globals.GetKey(ref_externals[r])]);
|
||||
RLOG("#section references = " << (end_sec - sec.ref_sec_index));
|
||||
for(r = sec.ref_sec_index; r < end_sec; r++)
|
||||
RLOG(NFormat("%04x", ref_sections[r]));
|
||||
}
|
||||
*/
|
||||
}
|
||||
14
uppsrc2/coff/uld/uld.h
Normal file
14
uppsrc2/coff/uld/uld.h
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef __uld_uld__
|
||||
#define __uld_uld__
|
||||
|
||||
#include <coff/coff.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
inline dword PeekIL(const void *p) { return Peek32le(p); }
|
||||
inline word PeekIW(const void *p) { return Peek16le(p); }
|
||||
|
||||
inline void PokeIL(const void *p, dword d) { return Poke32le(p, d); }
|
||||
inline void PokeIW(const void *p, word d) { return Poke16le(p, d); }
|
||||
|
||||
#endif//__uld_uld__
|
||||
30
uppsrc2/coff/uld/uld.upp
Normal file
30
uppsrc2/coff/uld/uld.upp
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
description "Ultimate++ COFF linker (GNU binutils compatible, faster)";
|
||||
|
||||
uses
|
||||
coff;
|
||||
|
||||
target(TEST) ld-test.exe;
|
||||
|
||||
target(!TEST) ld.exe;
|
||||
|
||||
link(GCC) "-v ";
|
||||
|
||||
file
|
||||
Main readonly separator,
|
||||
version.h,
|
||||
notes.txt,
|
||||
solved.txt,
|
||||
uld.h,
|
||||
dump.cpp,
|
||||
obj.h,
|
||||
object.cpp,
|
||||
linkjob.cpp,
|
||||
diff,
|
||||
main.cpp,
|
||||
Info readonly separator,
|
||||
Copying;
|
||||
|
||||
mainconfig
|
||||
"" = "",
|
||||
"" = ".TEST";
|
||||
|
||||
10
uppsrc2/coff/uld/version.h
Normal file
10
uppsrc2/coff/uld/version.h
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#ifndef _console_uld_version_h_
|
||||
#define _console_uld_version_h_
|
||||
|
||||
#define ULD_VERSION_MAJOR 1
|
||||
#define ULD_VERSION_MINOR 2
|
||||
#define ULD_VERSION_RELEASE 21
|
||||
#define ULD_DATE Date(2008, 3, 25)
|
||||
#define ULD_COPYRIGHT "Copyright (c) 2003-2006,2008 Tomas Rylek"
|
||||
|
||||
#endif
|
||||
698
uppsrc2/coff/util.cpp
Normal file
698
uppsrc2/coff/util.cpp
Normal file
|
|
@ -0,0 +1,698 @@
|
|||
// Copyright (C) 2003 Mirek Fidler, Tomas Rylek. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License (see COPYING) along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#include "coff.h"
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
#include <winver.h>
|
||||
#include <imagehlp.h>
|
||||
#endif
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
|
||||
#define DLLFILENAME "imagehlp.dll"
|
||||
#define DLIHEADER <coff/imagehlp.dli>
|
||||
#define DLIMODULE ImageHlp
|
||||
#include <Core/dli.h>
|
||||
|
||||
Vector<String> EnumWinRegSubkeys(const char *path, HKEY base_key) {
|
||||
HKEY key = 0;
|
||||
Vector<String> keys;
|
||||
if(RegOpenKeyEx(base_key, path, 0, KEY_READ, &key) != ERROR_SUCCESS)
|
||||
return keys;
|
||||
for(DWORD index = 0;; index++) {
|
||||
char name[1000];
|
||||
dword length = sizeof(name);
|
||||
FILETIME time;
|
||||
if(RegEnumKeyEx(key, index, name, &length, 0, NULL, NULL, &time) != ERROR_SUCCESS)
|
||||
break;
|
||||
keys.Add(String(name, length));
|
||||
}
|
||||
RegCloseKey(key);
|
||||
return keys;
|
||||
}
|
||||
|
||||
String TranslateCygWinPath(const char *path)
|
||||
{
|
||||
static String base_key = "SOFTWARE\\Cygnus Solutions\\Cygwin\\mounts v2";
|
||||
static String cygdrive = GetWinRegString("cygdrive prefix", base_key, HKEY_LOCAL_MACHINE);
|
||||
static Vector<String> root = EnumWinRegSubkeys(base_key, HKEY_LOCAL_MACHINE);
|
||||
static Vector<String> mount;
|
||||
if(mount.IsEmpty()) {
|
||||
mount.SetCount(root.GetCount());
|
||||
for(int i = 0; i < root.GetCount(); i++)
|
||||
mount[i] = GetWinRegString("native", base_key + "\\" + root[i], HKEY_LOCAL_MACHINE);
|
||||
}
|
||||
if(!memcmp(path, cygdrive, cygdrive.GetLength()) && path[cygdrive.GetLength()] == '/') {
|
||||
const char *drv = path + cygdrive.GetLength() + 1;
|
||||
if(IsAlpha(*drv) && drv[1] == '/')
|
||||
return AppendFileName(String(*drv, 1) + ":\\", drv + 2);
|
||||
}
|
||||
String bestroot, bestmount, bestrel;
|
||||
for(int i = 0; i < root.GetCount(); i++) {
|
||||
int l = root[i].GetLength();
|
||||
if(!memcmp(path, root[i], l) && (*root[i].Last() == '/' || path[l] == 0 || path[l] == '/')) {
|
||||
if(l > bestroot.GetLength()) {
|
||||
bestroot = root[i];
|
||||
bestmount = mount[i];
|
||||
const char *p = path + l;
|
||||
if(*p == '/')
|
||||
p++;
|
||||
bestrel = p;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!IsNull(bestroot))
|
||||
return AppendFileName(bestmount, bestrel);
|
||||
|
||||
return Null;
|
||||
}
|
||||
#endif
|
||||
|
||||
const char *EatPrefix(const char *string, const char *prefix)
|
||||
{
|
||||
int len = (int)strlen(prefix);
|
||||
return (!MemICmp(string, prefix, len) ? string + len : NULL);
|
||||
}
|
||||
|
||||
Vector<String> SplitCmdArgs(const char *cmd)
|
||||
{
|
||||
Vector<String> out;
|
||||
while(*cmd)
|
||||
if((byte)*cmd <= ' ')
|
||||
cmd++;
|
||||
else
|
||||
{
|
||||
String arg;
|
||||
while(*cmd > ' ')
|
||||
if(*cmd == '\"')
|
||||
{
|
||||
cmd++;
|
||||
while(*cmd && (*cmd != '\"' || *++cmd == '\"'))
|
||||
arg.Cat(*cmd++);
|
||||
}
|
||||
else
|
||||
arg.Cat(*cmd++);
|
||||
out.Add(arg);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
const char *FetchCmdArg(const Vector<String>& cmdlist, int& cmdi)
|
||||
{
|
||||
if(cmdi + 1 >= cmdlist.GetCount())
|
||||
throw Exc(NFormat("Argument missing for option '%s'.", cmdlist[cmdi]));
|
||||
return cmdlist[++cmdi];
|
||||
}
|
||||
|
||||
const char *FetchCmdArg(const Vector<String>& cmdlist, int& cmdi, const char *ptr)
|
||||
{
|
||||
return (ptr && *ptr ? ptr : FetchCmdArg(cmdlist, cmdi));
|
||||
}
|
||||
|
||||
int ScanCInt(const char *line)
|
||||
{
|
||||
while(*line && (byte)*line <= ' ')
|
||||
line++;
|
||||
bool sign = (*line == '-');
|
||||
if(sign || *line == '+')
|
||||
line++;
|
||||
if(!IsDigit(*line))
|
||||
return Null;
|
||||
int out = 0;
|
||||
if(*line == '0')
|
||||
{
|
||||
if(line[1] == 'x')
|
||||
{ // hexadecimal
|
||||
line += 2;
|
||||
if(!IsXDigit(*line))
|
||||
return Null;
|
||||
for(; IsXDigit(*line); line++)
|
||||
out = 16 * out + (*line <= '9' ? *line - '0' : (*line & ~0x20) - 'A' + 10);
|
||||
}
|
||||
else
|
||||
{ // octal
|
||||
while(unsigned(*++line - '0') < 8)
|
||||
out = 8 * out + *line - '0';
|
||||
}
|
||||
}
|
||||
else
|
||||
{ // decimal
|
||||
do
|
||||
out = 10 * out + *line++ - '0';
|
||||
while(IsDigit(*line));
|
||||
}
|
||||
return sign ? -out : out;
|
||||
}
|
||||
|
||||
static inline bool IsDirSep(char c) { return c == '/' || c == '\\'; }
|
||||
|
||||
String NormalizeRelPath(const char *path)
|
||||
{
|
||||
String out;
|
||||
while(*path)
|
||||
{
|
||||
while(IsDirSep(*path))
|
||||
{
|
||||
out.Cat('\\');
|
||||
path++;
|
||||
}
|
||||
const char *b = path;
|
||||
while(*path && !IsDirSep(*path))
|
||||
path++;
|
||||
if(path - b == 1 && *b == '.')
|
||||
{
|
||||
if(!out.IsEmpty() && !IsDirSep(*out.Last()))
|
||||
out.Cat('\\');
|
||||
while(IsDirSep(*path))
|
||||
path++;
|
||||
continue;
|
||||
}
|
||||
if(path - b == 2 && *b == '.' && b[1] == '.')
|
||||
{
|
||||
const char *o = out.Begin(), *e = out.End();
|
||||
if(e - o >= 2 && IsDirSep(e[-1]) && !IsDirSep(e[-2]))
|
||||
{
|
||||
e -= 2;
|
||||
while(e > o && !IsDirSep(e[-1]))
|
||||
e--;
|
||||
out.Trim(int(e - o));
|
||||
while(IsDirSep(*path))
|
||||
path++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
out.Cat(b, int(path - b));
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
int CatN0(Vector<byte>& out, int length)
|
||||
{
|
||||
int l = out.GetCount();
|
||||
out.AddN(length);
|
||||
memset(&out[l], 0, length);
|
||||
return l;
|
||||
}
|
||||
|
||||
int CatN(Vector<byte>& out, int length, const void *in)
|
||||
{
|
||||
int l = out.GetCount();
|
||||
if(length > 0)
|
||||
{
|
||||
out.AddN(length);
|
||||
if(in)
|
||||
memcpy(&out[l], in, length);
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
#ifdef PLATFORM_WIN32
|
||||
static String WipeClass(const char *p)
|
||||
{
|
||||
String out;
|
||||
while(*p)
|
||||
if(IsAlpha(*p) || *p == '_')
|
||||
{
|
||||
const char *b = p++;
|
||||
while(IsAlNum(*p) || *p == '_')
|
||||
p++;
|
||||
if(p - b == 5 && !memcmp(b, "class", 5))
|
||||
{
|
||||
while(*p == ' ')
|
||||
p++;
|
||||
}
|
||||
else
|
||||
out.Cat(b, int(p - b));
|
||||
}
|
||||
else
|
||||
out.Cat(*p++);
|
||||
return out;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline bool IsIdent(char c) { return IsAlNum(c) || c == '_'; }
|
||||
|
||||
static inline const char *ReadIdent(const char *p, int len)
|
||||
{
|
||||
const char *b = p;
|
||||
while(IsIdent(*p) && ++p - b < len)
|
||||
;
|
||||
return p;
|
||||
}
|
||||
|
||||
static const char *DemangleGccDeclarator(String& base, String& prefix, const char *p,
|
||||
Vector<String>& templmap, Vector<String>& argmap, bool is_template);
|
||||
|
||||
static const char *DemangleGccDeclarator(String& out, const char *p,
|
||||
Vector<String>& templmap, Vector<String>& argmap, bool is_template)
|
||||
{
|
||||
String base, prefix;
|
||||
p = DemangleGccDeclarator(base, prefix, p, templmap, argmap, is_template);
|
||||
out << base;
|
||||
if(!IsNull(prefix))
|
||||
out << ' ' << prefix;
|
||||
return p;
|
||||
}
|
||||
|
||||
static const char *DemangleGccDeclarator(String& out, String& prefix, const char *p,
|
||||
Vector<String>& templmap, Vector<String>& argmap, bool is_template)
|
||||
{
|
||||
String base;
|
||||
switch(*p++)
|
||||
{
|
||||
case 'b':
|
||||
base << "bool";
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
base << "char";
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
base << "double";
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
p = DemangleGccDeclarator(base, p, templmap, argmap, false);
|
||||
prefix = "(" + prefix + ")(";
|
||||
while(p && *p && *p != 'E')
|
||||
{
|
||||
if(*prefix.Last() != '(')
|
||||
prefix << ", ";
|
||||
p = DemangleGccDeclarator(prefix, p, templmap, argmap, false);
|
||||
}
|
||||
if(p && *p == 'E')
|
||||
p++;
|
||||
prefix.Cat(')');
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
base << "byte";
|
||||
break;
|
||||
|
||||
case 'E': // single argument
|
||||
p = DemangleGccDeclarator(base, p + 1, templmap, argmap, is_template);
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
{ // multiple arguments
|
||||
String tmpargs;
|
||||
// Vector<String> auxmap;
|
||||
while(p && *p && *p != 'E')
|
||||
{
|
||||
if(!tmpargs.IsEmpty())
|
||||
tmpargs.Cat(", ");
|
||||
String arg;
|
||||
p = DemangleGccDeclarator(arg, p, templmap, argmap, is_template);
|
||||
tmpargs.Cat(arg);
|
||||
}
|
||||
if(tmpargs[0] == '<' || !tmpargs.IsEmpty() && *tmpargs.Last() == '>')
|
||||
base << "< " << tmpargs << " >";
|
||||
else
|
||||
base << '<' << tmpargs << '>';
|
||||
if(p && *p == 'E')
|
||||
p++;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'i':
|
||||
base << "int";
|
||||
break;
|
||||
|
||||
case 'j':
|
||||
base << "unsigned";
|
||||
break;
|
||||
|
||||
case 'K':
|
||||
if(!IsNull(prefix))
|
||||
prefix = "const " + prefix;
|
||||
else
|
||||
base << "const ";
|
||||
p = DemangleGccDeclarator(base, prefix, p, templmap, argmap, is_template);
|
||||
break;
|
||||
|
||||
case 'L':
|
||||
if(*p == 'i')
|
||||
{
|
||||
int num = ScanInt(p + 1, &p);
|
||||
if(!IsNull(num))
|
||||
{
|
||||
base << num;
|
||||
break;
|
||||
}
|
||||
}
|
||||
goto UNKNOWN;
|
||||
|
||||
case 'm':
|
||||
base << "dword";
|
||||
break;
|
||||
|
||||
case 'P':
|
||||
prefix = "*" + prefix;
|
||||
p = DemangleGccDeclarator(base, prefix, p, templmap, argmap, is_template);
|
||||
break;
|
||||
|
||||
case 'R':
|
||||
prefix = "&" + prefix;
|
||||
p = DemangleGccDeclarator(base, prefix, p, templmap, argmap, is_template);
|
||||
break;
|
||||
|
||||
case 'S':
|
||||
{
|
||||
int equiv = 0;
|
||||
if(IsDigit(*p))
|
||||
{
|
||||
equiv = ScanInt(p, &p);
|
||||
if(equiv < 0)
|
||||
{
|
||||
base << "error(S)";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(*p++ != '_')
|
||||
{
|
||||
base << "error(S_)";
|
||||
return NULL;
|
||||
}
|
||||
if(!argmap.IsEmpty() && equiv == argmap.GetCount()) // ??
|
||||
base.Cat(argmap.Top());
|
||||
else if(equiv >= argmap.GetCount())
|
||||
{
|
||||
base << "error(S" << equiv << "_)";
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
base.Cat(argmap[equiv]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 'T':
|
||||
{
|
||||
int equiv = 0;
|
||||
if(IsDigit(*p))
|
||||
{
|
||||
equiv = ScanInt(p, &p);
|
||||
if(equiv < 0)
|
||||
{
|
||||
base << "error(T)";
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if(*p++ != '_')
|
||||
{
|
||||
base << "error(T_)";
|
||||
return NULL;
|
||||
}
|
||||
if(!templmap.IsEmpty() && equiv == templmap.GetCount()) // ??
|
||||
base.Cat(templmap.Top());
|
||||
else if(equiv >= templmap.GetCount())
|
||||
{
|
||||
base << "error(T" << equiv << "_)";
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
base.Cat(templmap[equiv]);
|
||||
}
|
||||
break;
|
||||
|
||||
case 't':
|
||||
base << "word";
|
||||
break;
|
||||
|
||||
case 'v': // void
|
||||
base << "void";
|
||||
break;
|
||||
|
||||
case 'z':
|
||||
base << "...";
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
{
|
||||
bool first = true;
|
||||
while(p && *p != 'E')
|
||||
{
|
||||
if(!IsDigit(*p))
|
||||
break;
|
||||
int ident = ScanInt(p, &p);
|
||||
if(ident <= 0)
|
||||
break;
|
||||
const char *b = p;
|
||||
p = ReadIdent(p, ident);
|
||||
if(p - b < ident)
|
||||
break;
|
||||
if(!first)
|
||||
base.Cat("::");
|
||||
base.Cat(b, int(p - b));
|
||||
if(*p == 'I')
|
||||
p = DemangleGccDeclarator(base, p, templmap, argmap, true);
|
||||
first = false;
|
||||
}
|
||||
if(!p)
|
||||
base << "(error)";
|
||||
else if(*p == 'E')
|
||||
p++;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if(IsDigit(*--p))
|
||||
{
|
||||
int ident = ScanInt(p, &p);
|
||||
if(ident <= 0)
|
||||
break;
|
||||
const char *b = p;
|
||||
p = ReadIdent(p, ident);
|
||||
if(p - b < ident)
|
||||
break;
|
||||
base.Cat(b, int(p - b));
|
||||
if(*p == 'I')
|
||||
p = DemangleGccDeclarator(base, p, templmap, argmap, true);
|
||||
break;
|
||||
}
|
||||
|
||||
UNKNOWN:
|
||||
base << "unknown " << *p;
|
||||
return NULL;
|
||||
}
|
||||
if(is_template)
|
||||
templmap.Add(base);
|
||||
argmap.Add(base);
|
||||
out.Cat(base);
|
||||
return p;
|
||||
}
|
||||
|
||||
const char *DemangleOperator(char a, char b)
|
||||
{
|
||||
const char *functor = NULL;
|
||||
/**/ if(a == 'e' && b == 'q') functor = "==";
|
||||
else if(a == 'n' && b == 'e') functor = "!=";
|
||||
else if(a == 'l' && b == 't') functor = "<";
|
||||
else if(a == 'l' && b == 'e') functor = "<=";
|
||||
else if(a == 'g' && b == 't') functor = ">";
|
||||
else if(a == 'g' && b == 'e') functor = ">=";
|
||||
else if(a == 'i' && b == 'x') functor = "[]";
|
||||
else if(a == 'r' && b == 'm') functor = "%";
|
||||
else if(a == 'p' && b == 'L') functor = "+=";
|
||||
else if(a == 'a' && b == 'S') functor = "=";
|
||||
else if(a == 'p' && b == 'l') functor = "+";
|
||||
else if(a == 'l' && b == 's') functor = "<<";
|
||||
else if(a == 'l' && b == 'S') functor = "<<=";
|
||||
return functor;
|
||||
}
|
||||
|
||||
String DemangleGccName(const char *name)
|
||||
{
|
||||
const char *p = name;
|
||||
if(*p++ != '_' || *p++ != '_' || *p++ != 'Z')
|
||||
return name;
|
||||
String out;
|
||||
bool method = (*p == 'N');
|
||||
if(method)
|
||||
p++;
|
||||
bool methconst = (*p == 'K');
|
||||
if(methconst)
|
||||
p++;
|
||||
if(IsDigit(*p))
|
||||
{
|
||||
if(!IsDigit(*p))
|
||||
return name;
|
||||
int ident = ScanInt(p, &p);
|
||||
if(ident <= 0)
|
||||
return name;
|
||||
const char *b = p;
|
||||
p = ReadIdent(p, ident);
|
||||
if(p - b < ident)
|
||||
return name;
|
||||
out.Cat(b, ident);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *functor = (*p ? DemangleOperator(p[0], p[1]) : NULL);
|
||||
if(!functor)
|
||||
return name;
|
||||
p += 2;
|
||||
out << "operator " << functor << ' ';
|
||||
}
|
||||
Vector<String> templmap, argmap;
|
||||
bool retval = false;
|
||||
if(*p == 'I')
|
||||
{
|
||||
String arg;
|
||||
p = DemangleGccDeclarator(arg, p, templmap, argmap, true);
|
||||
out.Cat(arg);
|
||||
retval = (!method);
|
||||
}
|
||||
if(!p)
|
||||
{
|
||||
out << "; " << name;
|
||||
return out;
|
||||
}
|
||||
String root = out;
|
||||
if(method)
|
||||
argmap.Add(out);
|
||||
if(method)
|
||||
{
|
||||
while(p && *p && *p != 'E' && *p != 'I')
|
||||
{
|
||||
int notempl = root.Find('<');
|
||||
if(notempl < 0)
|
||||
notempl = root.GetLength();
|
||||
if(*p == 'C')
|
||||
{
|
||||
retval = false;
|
||||
out.Cat("::");
|
||||
out.Cat(root, notempl);
|
||||
p++;
|
||||
if(*p != '1' && *p != '2')
|
||||
return name;
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
if(*p == 'D')
|
||||
{
|
||||
retval = false;
|
||||
out.Cat("::~");
|
||||
out.Cat(root, notempl);
|
||||
p++;
|
||||
if(*p != '0' && *p != '1' && *p != '2')
|
||||
return name;
|
||||
p++;
|
||||
break;
|
||||
}
|
||||
String subname, functor;
|
||||
if(*p == 'c' && p[1] == 'v')
|
||||
{
|
||||
retval = false;
|
||||
p += 2;
|
||||
subname << "operator ";
|
||||
p = DemangleGccDeclarator(subname, p, templmap, argmap, false);
|
||||
}
|
||||
else if(*p && !IsNull(functor = DemangleOperator(p[0], p[1])))
|
||||
p += 2;
|
||||
else if(!IsDigit(*p))
|
||||
return name;
|
||||
else
|
||||
{
|
||||
int ident = ScanInt(p, &p);
|
||||
if(ident <= 0)
|
||||
return name;
|
||||
const char *b = p;
|
||||
p = ReadIdent(p, ident);
|
||||
if(p - b < ident)
|
||||
return name;
|
||||
subname = String(b, ident);
|
||||
}
|
||||
if(!IsNull(functor))
|
||||
subname << "operator " << functor << ' ';
|
||||
out.Cat("::");
|
||||
out.Cat(subname);
|
||||
root = subname;
|
||||
// if(*p == 'I' || *p == 'E')
|
||||
// p = DemangleGccDeclarator(subname, p, templmap, argmap, false);
|
||||
}
|
||||
if(!p || *p != 'E')
|
||||
return name;
|
||||
p++;
|
||||
}
|
||||
if(retval)
|
||||
{
|
||||
String rvl;
|
||||
p = DemangleGccDeclarator(rvl, p, templmap, argmap, false);
|
||||
if(!rvl.IsEmpty() && IsIdent(*rvl.Last()))
|
||||
rvl.Cat(' ');
|
||||
rvl.Cat(out);
|
||||
out = rvl;
|
||||
}
|
||||
out.Cat('(');
|
||||
while(p && *p)
|
||||
{
|
||||
if(*out.Last() != '(')
|
||||
out.Cat(", ");
|
||||
String arg;
|
||||
p = DemangleGccDeclarator(arg, p, templmap, argmap, false);
|
||||
out.Cat(arg);
|
||||
argmap.Add(arg);
|
||||
}
|
||||
out.Cat(')');
|
||||
if(methconst)
|
||||
out.Cat(" const");
|
||||
// if(!p)
|
||||
out << "; " << name;
|
||||
return out;
|
||||
}
|
||||
|
||||
String DemangleName(String name, int mangling_style)
|
||||
{
|
||||
String out = name;
|
||||
#ifdef PLATFORM_WIN32
|
||||
if(mangling_style == MANGLING_MSC && ImageHlp())
|
||||
{
|
||||
char buffer[1024];
|
||||
ImageHlp().UnDecorateSymbolName(name, buffer, sizeof(buffer),
|
||||
UNDNAME_NO_ACCESS_SPECIFIERS | UNDNAME_NO_MEMBER_TYPE | UNDNAME_NO_MS_KEYWORDS);
|
||||
out = WipeClass(buffer);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(mangling_style == MANGLING_GCC)
|
||||
out = DemangleGccName(name);
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
String NormalizePathCase(String file)
|
||||
{
|
||||
#if PATH_HAS_CASE
|
||||
return file;
|
||||
#else
|
||||
return ToLower(file);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool EqualsPathCase(String f1, String f2)
|
||||
{
|
||||
#if PATH_HAS_CASE
|
||||
return f1 == f2;
|
||||
#else
|
||||
return !CompareNoCase(f1, f2);
|
||||
#endif
|
||||
}
|
||||
|
||||
void PutStdOut(const char *text)
|
||||
{
|
||||
puts(text);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
String MaxLenString(const byte *b, int maxlen)
|
||||
{
|
||||
const byte *e = b + maxlen;
|
||||
while(e > b && e[-1] == 0)
|
||||
e--;
|
||||
return String(b, int(e - b));
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
36
uppsrc2/coff/util.h
Normal file
36
uppsrc2/coff/util.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (C) 2003 Mirek Fidler, Tomas Rylek. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License (see COPYING) along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifndef _console_coff_util_h_
|
||||
#define _console_coff_util_h_
|
||||
|
||||
#ifdef __offsetof
|
||||
#undef __offsetof
|
||||
#endif
|
||||
|
||||
#ifdef PLATFORM_BSD
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
|
||||
#define __offsetof(obj, item) (int(&reinterpret_cast<obj *>(1)->item) - 1)
|
||||
|
||||
inline bool IsCIdent(char c) { return IsAlNum(c) || c == '_'; }
|
||||
|
||||
Vector<String> SplitCmdArgs(const char *cmdline);
|
||||
const char *FetchCmdArg(const Vector<String>& cmdlist, int& cmdi);
|
||||
const char *FetchCmdArg(const Vector<String>& cmdlist, int& cmdi, const char *ptr);
|
||||
const char *EatPrefix(const char *string, const char *prefix);
|
||||
int ScanCInt(const char *line);
|
||||
String NormalizeRelPath(const char *path);
|
||||
int CatN0(Vector<byte>& out, int length);
|
||||
int CatN(Vector<byte>& out, int length, const void *in);
|
||||
String NormalizePathCase(String file);
|
||||
bool EqualsPathCase(String f1, String f2);
|
||||
enum { MANGLING_NONE, MANGLING_MSC, MANGLING_GCC };
|
||||
String DemangleName(String name, int mangling_style);
|
||||
void PutStdOut(const char *text);
|
||||
String MaxLenString(const byte *b, int maxlen);
|
||||
#ifdef PLATFORM_WIN32
|
||||
String TranslateCygWinPath(const char *path);
|
||||
#endif
|
||||
#endif
|
||||
Loading…
Add table
Add a link
Reference in a new issue