mirror of
https://github.com/TinyCC/tinycc.git
synced 2025-11-16 12:34:45 +00:00
tcctools.c: integrate tiny_libmaker/_impdef
usage:
tcc -ar [rcsv] lib files...
tcc -impdef lib.dll [-v] [-o lib.def]
also:
- support more files with -c: tcc -c f1.c f2.c ...
- fix a bug which caused tcc f1.c f2.S to produce no asm
- allow tcc -ar @listfile too
- change prototype: _void_ tcc_set_options(...)
- apply -Wl,-whole-archive when a librariy is given
as libxxx.a also (not just for -lxxx)
This commit is contained in:
@@ -5,10 +5,6 @@
|
||||
@echo off
|
||||
setlocal
|
||||
|
||||
set VSCOMNTOOLS=%VS150COMNTOOLS%
|
||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
|
||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
|
||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
|
||||
set CC=gcc -Os -s
|
||||
set /p VERSION= < ..\VERSION
|
||||
set INST=
|
||||
@@ -70,10 +66,17 @@ goto :a1
|
||||
if not (%1)==() goto :usage
|
||||
|
||||
if not "%CC%"=="@call :cl" goto :p1
|
||||
set VSCOMNTOOLS=%VS150COMNTOOLS%
|
||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS140COMNTOOLS%
|
||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS130COMNTOOLS%
|
||||
if "%VSCOMNTOOLS%"=="" set VSCOMNTOOLS=%VS120COMNTOOLS%
|
||||
if %T%_==32_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\vcvars32.bat"
|
||||
if %T%_==64_ set CLVARS="%VSCOMNTOOLS%..\..\VC\bin\amd64\vcvars64.bat"
|
||||
if %T%_==_ set T=32& if %Platform%_==X64_ set T=64
|
||||
if %CLVARS%_==_ goto :p1
|
||||
if exist %CLVARS% call %CLVARS%
|
||||
:p1
|
||||
|
||||
if not %T%_==_ goto :p2
|
||||
set T=32
|
||||
if %PROCESSOR_ARCHITECTURE%_==AMD64_ set T=64
|
||||
@@ -97,9 +100,6 @@ set PX=i386-win32
|
||||
|
||||
@echo on
|
||||
|
||||
@if %CLVARS%_==_ goto :config.h
|
||||
call %CLVARS%
|
||||
|
||||
:config.h
|
||||
echo>..\config.h #define TCC_VERSION "%VERSION%"
|
||||
echo>> ..\config.h #ifdef TCC_TARGET_X86_64
|
||||
@@ -108,7 +108,7 @@ echo>> ..\config.h #else
|
||||
echo>> ..\config.h #define CONFIG_TCC_LIBPATHS "{B}/lib/32;{B}/lib"
|
||||
echo>> ..\config.h #endif
|
||||
|
||||
@del /q *tcc.exe tiny_*.exe *tcc.dll
|
||||
for %%f in (*tcc.exe *tcc.dll) do @del %%f
|
||||
|
||||
:compiler
|
||||
%CC% -o libtcc.dll -shared ..\libtcc.c %D% -DONE_SOURCE -DLIBTCC_AS_DLL
|
||||
@@ -116,10 +116,6 @@ echo>> ..\config.h #endif
|
||||
%CC% -o tcc.exe ..\tcc.c libtcc.dll %D%
|
||||
%CC% -o %PX%-tcc.exe ..\tcc.c %DX% -DONE_SOURCE
|
||||
|
||||
:tools
|
||||
%CC% -o tiny_impdef.exe tools\tiny_impdef.c %D%
|
||||
%CC% -o tiny_libmaker.exe tools\tiny_libmaker.c %D%
|
||||
|
||||
@if (%TCC_FILES%)==(no) goto :files-done
|
||||
|
||||
if not exist libtcc mkdir libtcc
|
||||
@@ -129,12 +125,11 @@ if not exist lib\64 mkdir lib\64
|
||||
copy>nul ..\include\*.h include
|
||||
copy>nul ..\tcclib.h include
|
||||
copy>nul ..\libtcc.h libtcc
|
||||
tiny_impdef libtcc.dll -o libtcc\libtcc.def
|
||||
copy>nul ..\tests\libtcc_test.c examples
|
||||
copy>nul tcc-win32.txt doc
|
||||
|
||||
copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe
|
||||
%CC% -o tiny_libmaker-m%TX%.exe tools\tiny_libmaker.c %DX%
|
||||
.\tcc -impdef libtcc.dll -o libtcc\libtcc.def
|
||||
@if errorlevel 1 goto :the_end
|
||||
|
||||
:libtcc1.a
|
||||
@set O1=libtcc1.o crt1.o crt1w.o wincrt1.o wincrt1w.o dllcrt1.o dllmain.o chkstk.o bcheck.o
|
||||
@@ -149,7 +144,7 @@ copy>nul tiny_libmaker.exe tiny_libmaker-m%T%.exe
|
||||
.\tcc -m32 %D32% -w -c ../lib/bcheck.c
|
||||
.\tcc -m32 %D32% -c ../lib/alloca86.S
|
||||
.\tcc -m32 %D32% -c ../lib/alloca86-bt.S
|
||||
tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
|
||||
.\tcc -m32 -ar lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
|
||||
@if errorlevel 1 goto :the_end
|
||||
.\tcc -m64 %D64% -c ../lib/libtcc1.c
|
||||
.\tcc -m64 %D64% -c lib/crt1.c
|
||||
@@ -162,7 +157,7 @@ tiny_libmaker-m32 lib/32/libtcc1.a %O1% alloca86.o alloca86-bt.o
|
||||
.\tcc -m64 %D64% -w -c ../lib/bcheck.c
|
||||
.\tcc -m64 %D64% -c ../lib/alloca86_64.S
|
||||
.\tcc -m64 %D64% -c ../lib/alloca86_64-bt.S
|
||||
tiny_libmaker-m64 lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
|
||||
.\tcc -m64 -ar lib/64/libtcc1.a %O1% alloca86_64.o alloca86_64-bt.o
|
||||
@if errorlevel 1 goto :the_end
|
||||
|
||||
:tcc-doc.html
|
||||
@@ -172,7 +167,7 @@ cmd /c makeinfo --html --no-split ../tcc-doc.texi -o doc/tcc-doc.html
|
||||
:doc-done
|
||||
|
||||
:files-done
|
||||
@del /q *.o *.def *-m??.exe
|
||||
for %%f in (*.o *.def) do @del %%f
|
||||
|
||||
:copy-install
|
||||
@if (%INST%)==() goto :the_end
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
For the 'Hello DLL' example type
|
||||
|
||||
tcc -shared dll.c
|
||||
tiny_impdef dll.dll (optional)
|
||||
tcc -impdef dll.dll (optional)
|
||||
tcc hello_dll.c dll.def
|
||||
|
||||
|
||||
@@ -66,10 +66,10 @@
|
||||
To link with Windows system DLLs, TCC uses import definition
|
||||
files (.def) instead of libraries.
|
||||
|
||||
The included 'tiny_impdef' program may be used to make additional
|
||||
.def files for any DLL. For example:
|
||||
The now built-in 'tiny_impdef' program may be used to make
|
||||
additional .def files for any DLL. For example
|
||||
|
||||
tiny_impdef.exe opengl32.dll
|
||||
tcc -impdef [-v] opengl32.dll [-o opengl32.def]
|
||||
|
||||
Put opengl32.def into the tcc/lib directory. Specify -lopengl32 at
|
||||
the TCC commandline to link a program that uses opengl32.dll.
|
||||
@@ -98,10 +98,10 @@
|
||||
|
||||
Tiny Libmaker:
|
||||
--------------
|
||||
The included tiny_libmaker tool by Timovj Lahde can be used as
|
||||
The now built-in tiny_libmaker tool by Timovj Lahde can be used as
|
||||
'ar' replacement to make a library from several object files:
|
||||
|
||||
tiny_libmaker [rcs] library objectfiles ...
|
||||
tcc -ar [rcsv] library objectfiles ...
|
||||
|
||||
|
||||
Compilation from source:
|
||||
@@ -143,15 +143,13 @@
|
||||
------------
|
||||
- On the object file level, currently TCC supports only the ELF format,
|
||||
not COFF as used by MinGW and MSVC. It is not possible to exchange
|
||||
object files or libraries between TCC and these compilers. However
|
||||
libraries for TCC from objects by TCC can be made using tiny_libmaker
|
||||
or MinGW's ar.
|
||||
object files or libraries between TCC and these compilers.
|
||||
|
||||
However libraries for TCC from objects by TCC can be made using
|
||||
tcc -ar lib.a files.o ,,,
|
||||
|
||||
- No leading underscore is generated in the ELF symbols.
|
||||
|
||||
- Bounds checking (option -b) is not supported on 64-bit OS.
|
||||
|
||||
|
||||
Documentation and License:
|
||||
--------------------------
|
||||
TCC is distributed under the GNU Lesser General Public License. (See
|
||||
|
||||
@@ -1,249 +0,0 @@
|
||||
/* -------------------------------------------------------------- */
|
||||
/*
|
||||
* tiny_impdef creates an export definition file (.def) from a dll
|
||||
* on MS-Windows. Usage: tiny_impdef library.dll [-o outputfile]"
|
||||
*
|
||||
* Copyright (c) 2005,2007 grischka
|
||||
*
|
||||
* 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef TINY_IMPDEF_GET_EXPORT_NAMES_ONLY
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <malloc.h>
|
||||
|
||||
static char *get_export_names(int fd);
|
||||
#define tcc_free free
|
||||
#define tcc_realloc realloc
|
||||
|
||||
/* extract the basename of a file */
|
||||
static char *file_basename(const char *name)
|
||||
{
|
||||
const char *p = strchr(name, 0);
|
||||
while (p > name
|
||||
&& p[-1] != '/'
|
||||
&& p[-1] != '\\'
|
||||
)
|
||||
--p;
|
||||
return (char*)p;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int ret, v, i;
|
||||
char infile[MAX_PATH];
|
||||
char outfile[MAX_PATH];
|
||||
|
||||
static const char *ext[] = { ".dll", ".exe", NULL };
|
||||
const char *file, **pp;
|
||||
char path[MAX_PATH], *p, *q;
|
||||
FILE *fp, *op;
|
||||
|
||||
infile[0] = 0;
|
||||
outfile[0] = 0;
|
||||
fp = op = NULL;
|
||||
v = 0;
|
||||
ret = 1;
|
||||
p = NULL;
|
||||
|
||||
for (i = 1; i < argc; ++i) {
|
||||
const char *a = argv[i];
|
||||
if ('-' == a[0]) {
|
||||
if (0 == strcmp(a, "-v")) {
|
||||
v = 1;
|
||||
} else if (0 == strcmp(a, "-o")) {
|
||||
if (++i == argc)
|
||||
goto usage;
|
||||
strcpy(outfile, argv[i]);
|
||||
} else
|
||||
goto usage;
|
||||
} else if (0 == infile[0])
|
||||
strcpy(infile, a);
|
||||
else
|
||||
goto usage;
|
||||
}
|
||||
|
||||
if (0 == infile[0]) {
|
||||
usage:
|
||||
fprintf(stderr,
|
||||
"tiny_impdef: create export definition file (.def) from a dll\n"
|
||||
"Usage: tiny_impdef library.dll [-o outputfile]\n"
|
||||
);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
if (0 == outfile[0])
|
||||
{
|
||||
strcpy(outfile, file_basename(infile));
|
||||
q = strrchr(outfile, '.');
|
||||
if (NULL == q)
|
||||
q = strchr(outfile, 0);
|
||||
strcpy(q, ".def");
|
||||
}
|
||||
|
||||
file = infile;
|
||||
|
||||
#ifdef _WIN32
|
||||
pp = ext;
|
||||
do if (SearchPath(NULL, file, *pp, sizeof path, path, NULL)) {
|
||||
file = path;
|
||||
break;
|
||||
} while (*pp++);
|
||||
#endif
|
||||
|
||||
fp = fopen(file, "rb");
|
||||
if (NULL == fp) {
|
||||
fprintf(stderr, "tiny_impdef: no such file: %s\n", infile);
|
||||
goto the_end;
|
||||
}
|
||||
if (v)
|
||||
printf("--> %s\n", file);
|
||||
|
||||
p = get_export_names(fileno(fp));
|
||||
if (NULL == p) {
|
||||
fprintf(stderr, "tiny_impdef: could not get exported function names.\n");
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
op = fopen(outfile, "w");
|
||||
if (NULL == op) {
|
||||
fprintf(stderr, "tiny_impdef: could not create output file: %s\n", outfile);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
fprintf(op, "LIBRARY %s\n\nEXPORTS\n", file_basename(file));
|
||||
for (q = p, i = 0; *q; ++i) {
|
||||
fprintf(op, "%s\n", q);
|
||||
q += strlen(q) + 1;
|
||||
}
|
||||
|
||||
if (v) {
|
||||
printf("<-- %s\n", outfile);
|
||||
printf("%d symbol(s) found\n", i);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
||||
the_end:
|
||||
if (p)
|
||||
free(p);
|
||||
if (fp)
|
||||
fclose(fp);
|
||||
if (op)
|
||||
fclose(op);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int read_mem(int fd, unsigned offset, void *buffer, unsigned len)
|
||||
{
|
||||
lseek(fd, offset, SEEK_SET);
|
||||
return len == read(fd, buffer, len);
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
|
||||
#if defined TCC_TARGET_X86_64
|
||||
# define IMAGE_FILE_MACHINE 0x8664
|
||||
#elif defined TCC_TARGET_ARM
|
||||
# define IMAGE_FILE_MACHINE 0x01C0
|
||||
#elif 1 /* defined TCC_TARGET_I386 */
|
||||
# define IMAGE_FILE_MACHINE 0x014C
|
||||
#endif
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
#endif
|
||||
|
||||
static char *get_export_names(int fd)
|
||||
{
|
||||
int l, i, n, n0;
|
||||
char *p;
|
||||
|
||||
IMAGE_SECTION_HEADER ish;
|
||||
IMAGE_EXPORT_DIRECTORY ied;
|
||||
IMAGE_DOS_HEADER dh;
|
||||
IMAGE_FILE_HEADER ih;
|
||||
DWORD sig, ref, addr, ptr, namep;
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
IMAGE_OPTIONAL_HEADER64 oh;
|
||||
#else
|
||||
IMAGE_OPTIONAL_HEADER32 oh;
|
||||
#endif
|
||||
int pef_hdroffset, opt_hdroffset, sec_hdroffset;
|
||||
|
||||
n = n0 = 0;
|
||||
p = NULL;
|
||||
|
||||
if (!read_mem(fd, 0, &dh, sizeof dh))
|
||||
goto the_end;
|
||||
if (!read_mem(fd, dh.e_lfanew, &sig, sizeof sig))
|
||||
goto the_end;
|
||||
if (sig != 0x00004550)
|
||||
goto the_end;
|
||||
pef_hdroffset = dh.e_lfanew + sizeof sig;
|
||||
if (!read_mem(fd, pef_hdroffset, &ih, sizeof ih))
|
||||
goto the_end;
|
||||
if (IMAGE_FILE_MACHINE != ih.Machine)
|
||||
goto the_end;
|
||||
opt_hdroffset = pef_hdroffset + sizeof ih;
|
||||
sec_hdroffset = opt_hdroffset + sizeof oh;
|
||||
if (!read_mem(fd, opt_hdroffset, &oh, sizeof oh))
|
||||
goto the_end;
|
||||
|
||||
if (IMAGE_DIRECTORY_ENTRY_EXPORT >= oh.NumberOfRvaAndSizes)
|
||||
goto the_end;
|
||||
|
||||
addr = oh.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
|
||||
//printf("addr: %08x\n", addr);
|
||||
for (i = 0; i < ih.NumberOfSections; ++i) {
|
||||
if (!read_mem(fd, sec_hdroffset + i * sizeof ish, &ish, sizeof ish))
|
||||
goto the_end;
|
||||
//printf("vaddr: %08x\n", ish.VirtualAddress);
|
||||
if (addr >= ish.VirtualAddress && addr < ish.VirtualAddress + ish.SizeOfRawData)
|
||||
goto found;
|
||||
}
|
||||
goto the_end;
|
||||
|
||||
found:
|
||||
ref = ish.VirtualAddress - ish.PointerToRawData;
|
||||
if (!read_mem(fd, addr - ref, &ied, sizeof ied))
|
||||
goto the_end;
|
||||
|
||||
namep = ied.AddressOfNames - ref;
|
||||
for (i = 0; i < ied.NumberOfNames; ++i) {
|
||||
if (!read_mem(fd, namep, &ptr, sizeof ptr))
|
||||
goto the_end;
|
||||
namep += sizeof ptr;
|
||||
for (l = 0;;) {
|
||||
if (n+1 >= n0)
|
||||
p = tcc_realloc(p, n0 = n0 ? n0 * 2 : 256);
|
||||
if (!read_mem(fd, ptr - ref + l++, p + n, 1)) {
|
||||
tcc_free(p), p = NULL;
|
||||
goto the_end;
|
||||
}
|
||||
if (p[n++] == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (p)
|
||||
p[n] = 0;
|
||||
the_end:
|
||||
return p;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------- */
|
||||
@@ -1,278 +0,0 @@
|
||||
/*
|
||||
* This program is for making libtcc1.a without ar
|
||||
* tiny_libmaker - tiny elf lib maker
|
||||
* usage: tiny_libmaker [lib] files...
|
||||
* Copyright (c) 2007 Timppa
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../../elf.h"
|
||||
|
||||
#ifdef TCC_TARGET_X86_64
|
||||
# define ELFCLASSW ELFCLASS64
|
||||
# define ElfW(type) Elf##64##_##type
|
||||
# define ELFW(type) ELF##64##_##type
|
||||
#else
|
||||
# define ELFCLASSW ELFCLASS32
|
||||
# define ElfW(type) Elf##32##_##type
|
||||
# define ELFW(type) ELF##32##_##type
|
||||
#endif
|
||||
|
||||
#define ARMAG "!<arch>\n"
|
||||
#define ARFMAG "`\n"
|
||||
|
||||
typedef struct ArHdr {
|
||||
char ar_name[16];
|
||||
char ar_date[12];
|
||||
char ar_uid[6];
|
||||
char ar_gid[6];
|
||||
char ar_mode[8];
|
||||
char ar_size[10];
|
||||
char ar_fmag[2];
|
||||
} ArHdr;
|
||||
|
||||
unsigned long le2belong(unsigned long ul) {
|
||||
return ((ul & 0xFF0000)>>8)+((ul & 0xFF000000)>>24) +
|
||||
((ul & 0xFF)<<24)+((ul & 0xFF00)<<8);
|
||||
}
|
||||
|
||||
ArHdr arhdr = {
|
||||
"/ ",
|
||||
" ",
|
||||
"0 ",
|
||||
"0 ",
|
||||
"0 ",
|
||||
" ",
|
||||
ARFMAG
|
||||
};
|
||||
|
||||
ArHdr arhdro = {
|
||||
" ",
|
||||
" ",
|
||||
"0 ",
|
||||
"0 ",
|
||||
"0 ",
|
||||
" ",
|
||||
ARFMAG
|
||||
};
|
||||
|
||||
/* Returns 1 if s contains any of the chars of list, else 0 */
|
||||
int contains_any(const char *s, const char *list) {
|
||||
const char *l;
|
||||
for (; *s; s++) {
|
||||
for (l = list; *l; l++) {
|
||||
if (*s == *l)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usage(int ret) {
|
||||
fprintf(stderr, "usage: tiny_libmaker [rcsv] lib file...\n");
|
||||
fprintf(stderr, "Always creates a new lib. [abdioptxN] are explicitly rejected.\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
FILE *fi, *fh = NULL, *fo = NULL;
|
||||
ElfW(Ehdr) *ehdr;
|
||||
ElfW(Shdr) *shdr;
|
||||
ElfW(Sym) *sym;
|
||||
int i, fsize, i_lib, i_obj;
|
||||
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
|
||||
int symtabsize = 0;//, strtabsize = 0;
|
||||
char *anames = NULL;
|
||||
int *afpos = NULL;
|
||||
int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
|
||||
char tfile[260], stmp[20];
|
||||
char *file, *name;
|
||||
int ret = 2;
|
||||
char *ops_conflict = "habdioptxN"; // unsupported but destructive if ignored.
|
||||
int verbose = 0;
|
||||
|
||||
i_lib = 0; i_obj = 0; // will hold the index of the lib and first obj
|
||||
for (i = 1; i < argc; i++) {
|
||||
const char *a = argv[i];
|
||||
if (*a == '-' && strstr(a, "."))
|
||||
return usage(1); // -x.y is always invalid (same as gnu ar)
|
||||
if ((*a == '-') || (i == 1 && !strstr(a, "."))) { // options argument
|
||||
if (contains_any(a, ops_conflict))
|
||||
return usage(1);
|
||||
if (strstr(a, "v"))
|
||||
verbose = 1;
|
||||
} else { // lib or obj files: don't abort - keep validating all args.
|
||||
if (!i_lib) // first file is the lib
|
||||
i_lib = i;
|
||||
else if (!i_obj) // second file is the first obj
|
||||
i_obj = i;
|
||||
}
|
||||
}
|
||||
if (!i_obj) // i_obj implies also i_lib. we require both.
|
||||
return usage(1);
|
||||
|
||||
if ((fh = fopen(argv[i_lib], "wb")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open file %s \n", argv[i_lib]);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
sprintf(tfile, "%s.tmp", argv[i_lib]);
|
||||
if ((fo = fopen(tfile, "wb+")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't create temporary file %s\n", tfile);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
funcmax = 250;
|
||||
afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
||||
memcpy(&arhdro.ar_mode, "100666", 6);
|
||||
|
||||
// i_obj = first input object file
|
||||
while (i_obj < argc)
|
||||
{
|
||||
if (*argv[i_obj] == '-') { // by now, all options start with '-'
|
||||
i_obj++;
|
||||
continue;
|
||||
}
|
||||
if (verbose)
|
||||
printf("a - %s\n", argv[i_obj]);
|
||||
|
||||
if ((fi = fopen(argv[i_obj], "rb")) == NULL)
|
||||
{
|
||||
fprintf(stderr, "Can't open file %s \n", argv[i_obj]);
|
||||
goto the_end;
|
||||
}
|
||||
fseek(fi, 0, SEEK_END);
|
||||
fsize = ftell(fi);
|
||||
fseek(fi, 0, SEEK_SET);
|
||||
buf = malloc(fsize + 1);
|
||||
fread(buf, fsize, 1, fi);
|
||||
fclose(fi);
|
||||
|
||||
// elf header
|
||||
ehdr = (ElfW(Ehdr) *)buf;
|
||||
if (ehdr->e_ident[4] != ELFCLASSW)
|
||||
{
|
||||
fprintf(stderr, "Unsupported Elf Class: %s\n", argv[i_obj]);
|
||||
goto the_end;
|
||||
}
|
||||
|
||||
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + ehdr->e_shstrndx * ehdr->e_shentsize);
|
||||
shstr = (char *)(buf + shdr->sh_offset);
|
||||
for (i = 0; i < ehdr->e_shnum; i++)
|
||||
{
|
||||
shdr = (ElfW(Shdr) *) (buf + ehdr->e_shoff + i * ehdr->e_shentsize);
|
||||
if (!shdr->sh_offset)
|
||||
continue;
|
||||
if (shdr->sh_type == SHT_SYMTAB)
|
||||
{
|
||||
symtab = (char *)(buf + shdr->sh_offset);
|
||||
symtabsize = shdr->sh_size;
|
||||
}
|
||||
if (shdr->sh_type == SHT_STRTAB)
|
||||
{
|
||||
if (!strcmp(shstr + shdr->sh_name, ".strtab"))
|
||||
{
|
||||
strtab = (char *)(buf + shdr->sh_offset);
|
||||
//strtabsize = shdr->sh_size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (symtab && symtabsize)
|
||||
{
|
||||
int nsym = symtabsize / sizeof(ElfW(Sym));
|
||||
//printf("symtab: info size shndx name\n");
|
||||
for (i = 1; i < nsym; i++)
|
||||
{
|
||||
sym = (ElfW(Sym) *) (symtab + i * sizeof(ElfW(Sym)));
|
||||
if (sym->st_shndx &&
|
||||
(sym->st_info == 0x10
|
||||
|| sym->st_info == 0x11
|
||||
|| sym->st_info == 0x12
|
||||
)) {
|
||||
//printf("symtab: %2Xh %4Xh %2Xh %s\n", sym->st_info, sym->st_size, sym->st_shndx, strtab + sym->st_name);
|
||||
istrlen = strlen(strtab + sym->st_name)+1;
|
||||
anames = realloc(anames, strpos+istrlen);
|
||||
strcpy(anames + strpos, strtab + sym->st_name);
|
||||
strpos += istrlen;
|
||||
if (++funccnt >= funcmax) {
|
||||
funcmax += 250;
|
||||
afpos = realloc(afpos, funcmax * sizeof *afpos); // 250 func more
|
||||
}
|
||||
afpos[funccnt] = fpos;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
file = argv[i_obj];
|
||||
for (name = strchr(file, 0);
|
||||
name > file && name[-1] != '/' && name[-1] != '\\';
|
||||
--name);
|
||||
istrlen = strlen(name);
|
||||
if (istrlen >= sizeof(arhdro.ar_name))
|
||||
istrlen = sizeof(arhdro.ar_name) - 1;
|
||||
memset(arhdro.ar_name, ' ', sizeof(arhdro.ar_name));
|
||||
memcpy(arhdro.ar_name, name, istrlen);
|
||||
arhdro.ar_name[istrlen] = '/';
|
||||
sprintf(stmp, "%-10d", fsize);
|
||||
memcpy(&arhdro.ar_size, stmp, 10);
|
||||
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
||||
fwrite(buf, fsize, 1, fo);
|
||||
free(buf);
|
||||
i_obj++;
|
||||
fpos += (fsize + sizeof(arhdro));
|
||||
}
|
||||
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
|
||||
fpos = 0;
|
||||
if ((hofs & 1)) // align
|
||||
hofs++, fpos = 1;
|
||||
// write header
|
||||
fwrite("!<arch>\n", 8, 1, fh);
|
||||
sprintf(stmp, "%-10d", (int)(strpos + (funccnt+1) * sizeof(int)));
|
||||
memcpy(&arhdr.ar_size, stmp, 10);
|
||||
fwrite(&arhdr, sizeof(arhdr), 1, fh);
|
||||
afpos[0] = le2belong(funccnt);
|
||||
for (i=1; i<=funccnt; i++)
|
||||
afpos[i] = le2belong(afpos[i] + hofs);
|
||||
fwrite(afpos, (funccnt+1) * sizeof(int), 1, fh);
|
||||
fwrite(anames, strpos, 1, fh);
|
||||
if (fpos)
|
||||
fwrite("", 1, 1, fh);
|
||||
// write objects
|
||||
fseek(fo, 0, SEEK_END);
|
||||
fsize = ftell(fo);
|
||||
fseek(fo, 0, SEEK_SET);
|
||||
buf = malloc(fsize + 1);
|
||||
fread(buf, fsize, 1, fo);
|
||||
fwrite(buf, fsize, 1, fh);
|
||||
free(buf);
|
||||
ret = 0;
|
||||
the_end:
|
||||
if (anames)
|
||||
free(anames);
|
||||
if (afpos)
|
||||
free(afpos);
|
||||
if (fh)
|
||||
fclose(fh);
|
||||
if (fo)
|
||||
fclose(fo), remove(tfile);
|
||||
return ret;
|
||||
}
|
||||
Reference in New Issue
Block a user