coff moved to uppsrc2

git-svn-id: svn://ultimatepp.org/upp/trunk@7711 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2014-09-21 15:46:17 +00:00
parent 9ab355b225
commit c863f38e22
38 changed files with 8801 additions and 0 deletions

22
uppsrc2/coff/Copying Normal file
View 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.

View 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.

View 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

View 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

View 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
View 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
View file

@ -0,0 +1,6 @@
#include "coff.h"
void Main()
{
}

22
uppsrc2/coff/coff.h Normal file
View 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
View 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
View 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
View 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

View file

@ -0,0 +1 @@
FN_C(DWORD, __stdcall, UnDecorateSymbolName, (PCSTR dn, PSTR udn, DWORD len, DWORD Flags))

4
uppsrc2/coff/init Normal file
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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";

View 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
View 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
View 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 ? &section_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 ? &section_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
View 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
View 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

File diff suppressed because it is too large Load diff

118
uppsrc2/coff/uld/main.cpp Normal file
View 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);
}
}

View 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
View 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
View 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
View 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
View 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";

View 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
View 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
View 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