mirror of
https://github.com/frida/tinycc
synced 2024-12-26 15:06:58 +03:00
tiny_libmaker: more robust arguments interpretation
- Syntax is now much closer to gnu ar, but still supports whatever was supported before, with the following exceptions (which gnu ar has too): - lib is now mandatory (was optional and defaulted to ar_test.a before). - Path cannot start with '-' (but ./-myfile.o is OK). - Unlike gnu ar, modes are still optional (as before). - Now supports also (like gnu ar): - First argument as options doesn't have to start with '-', later options do. - Now supports mode v (verbose) with same output format as gnu ar. - Any names for lib/objs (were limited to .a/.o - broke cmake on windows). - Now explicitly fail on options which would be destructive for the user. - Now doesn't get confused by options between file arguments. - Still ignores other unknown options - as before. - Now doesn't read out-of-bounds if an option is one char. - As a result, cmake for windows can now use tiny_libmaker as ar, and configure can also detect tiny_libmaker as a valid ar (both couldn't before). Ignoring all options could previously cause to misinterpret the mode in a destructive way, e.g. if the user wanted to do something with an existing archive (such as p - print, or x - extract, etc), then it would instead just delete (re-create) the archive. Modes which can be destructive if ignored now explicitly fail. These include [habdioptxN]. Note that 'h' can be ignored, but this way we also implicitly print the usage for -h/--help. The .a/.o name limitations previously resulted in complete failure on some cases, such as cmake on windows which uses <filename>.obj and <libname>.lib . Fixed: e.g. 'tiny_libmaker r x.a x.o' was reading out of bounds [-1] for 'r'.
This commit is contained in:
parent
1ca685f887
commit
100f94be99
@ -71,50 +71,69 @@ ArHdr arhdro = {
|
|||||||
ARFMAG
|
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)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
FILE *fi, *fh = NULL, *fo = NULL;
|
FILE *fi, *fh = NULL, *fo = NULL;
|
||||||
ElfW(Ehdr) *ehdr;
|
ElfW(Ehdr) *ehdr;
|
||||||
ElfW(Shdr) *shdr;
|
ElfW(Shdr) *shdr;
|
||||||
ElfW(Sym) *sym;
|
ElfW(Sym) *sym;
|
||||||
int i, fsize, iarg;
|
int i, fsize, i_lib, i_obj;
|
||||||
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
|
char *buf, *shstr, *symtab = NULL, *strtab = NULL;
|
||||||
int symtabsize = 0;//, strtabsize = 0;
|
int symtabsize = 0;//, strtabsize = 0;
|
||||||
char *anames = NULL;
|
char *anames = NULL;
|
||||||
int *afpos = NULL;
|
int *afpos = NULL;
|
||||||
int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
|
int istrlen, strpos = 0, fpos = 0, funccnt = 0, funcmax, hofs;
|
||||||
char afile[260], tfile[260], stmp[20];
|
char tfile[260], stmp[20];
|
||||||
char *file, *name;
|
char *file, *name;
|
||||||
int ret = 2;
|
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) // implies also no i_lib
|
||||||
|
return usage(1);
|
||||||
|
|
||||||
strcpy(afile, "ar_test.a");
|
if ((fh = fopen(argv[i_lib], "wb")) == NULL)
|
||||||
iarg = 1;
|
|
||||||
|
|
||||||
if (argc < 2)
|
|
||||||
{
|
{
|
||||||
printf("usage: tiny_libmaker [lib] file...\n");
|
fprintf(stderr, "Can't open file %s \n", argv[i_lib]);
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
for (i=1; i<argc; i++) {
|
|
||||||
istrlen = strlen(argv[i]);
|
|
||||||
if (argv[i][istrlen-2] == '.') {
|
|
||||||
if(argv[i][istrlen-1] == 'a')
|
|
||||||
strcpy(afile, argv[i]);
|
|
||||||
else if(argv[i][istrlen-1] == 'o') {
|
|
||||||
iarg = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((fh = fopen(afile, "wb")) == NULL)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Can't open file %s \n", afile);
|
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprintf(tfile, "%s.tmp", afile);
|
sprintf(tfile, "%s.tmp", argv[i_lib]);
|
||||||
if ((fo = fopen(tfile, "wb+")) == NULL)
|
if ((fo = fopen(tfile, "wb+")) == NULL)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Can't create temporary file %s\n", tfile);
|
fprintf(stderr, "Can't create temporary file %s\n", tfile);
|
||||||
@ -125,16 +144,19 @@ int main(int argc, char **argv)
|
|||||||
afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
afpos = realloc(NULL, funcmax * sizeof *afpos); // 250 func
|
||||||
memcpy(&arhdro.ar_mode, "100666", 6);
|
memcpy(&arhdro.ar_mode, "100666", 6);
|
||||||
|
|
||||||
//iarg = 1;
|
// i_obj = first input object file
|
||||||
while (iarg < argc)
|
while (i_obj < argc)
|
||||||
{
|
{
|
||||||
if (!strcmp(argv[iarg], "rcs")) {
|
if (*argv[i_obj] == '-') { // by now, all options start with '-'
|
||||||
iarg++;
|
i_obj++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if ((fi = fopen(argv[iarg], "rb")) == NULL)
|
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[iarg]);
|
fprintf(stderr, "Can't open file %s \n", argv[i_obj]);
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
fseek(fi, 0, SEEK_END);
|
fseek(fi, 0, SEEK_END);
|
||||||
@ -144,13 +166,11 @@ int main(int argc, char **argv)
|
|||||||
fread(buf, fsize, 1, fi);
|
fread(buf, fsize, 1, fi);
|
||||||
fclose(fi);
|
fclose(fi);
|
||||||
|
|
||||||
//printf("%s:\n", argv[iarg]);
|
|
||||||
|
|
||||||
// elf header
|
// elf header
|
||||||
ehdr = (ElfW(Ehdr) *)buf;
|
ehdr = (ElfW(Ehdr) *)buf;
|
||||||
if (ehdr->e_ident[4] != ELFCLASSW)
|
if (ehdr->e_ident[4] != ELFCLASSW)
|
||||||
{
|
{
|
||||||
fprintf(stderr, "Unsupported Elf Class: %s\n", argv[iarg]);
|
fprintf(stderr, "Unsupported Elf Class: %s\n", argv[i_obj]);
|
||||||
goto the_end;
|
goto the_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -202,7 +222,7 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file = argv[iarg];
|
file = argv[i_obj];
|
||||||
for (name = strchr(file, 0);
|
for (name = strchr(file, 0);
|
||||||
name > file && name[-1] != '/' && name[-1] != '\\';
|
name > file && name[-1] != '/' && name[-1] != '\\';
|
||||||
--name);
|
--name);
|
||||||
@ -217,7 +237,7 @@ int main(int argc, char **argv)
|
|||||||
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
fwrite(&arhdro, sizeof(arhdro), 1, fo);
|
||||||
fwrite(buf, fsize, 1, fo);
|
fwrite(buf, fsize, 1, fo);
|
||||||
free(buf);
|
free(buf);
|
||||||
iarg++;
|
i_obj++;
|
||||||
fpos += (fsize + sizeof(arhdro));
|
fpos += (fsize + sizeof(arhdro));
|
||||||
}
|
}
|
||||||
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
|
hofs = 8 + sizeof(arhdr) + strpos + (funccnt+1) * sizeof(int);
|
||||||
|
Loading…
Reference in New Issue
Block a user