Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[PATCH] dxe3gen: add support for using an exports file.

9 views
Skip to first unread message

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 30, 2023, 12:31:16 PM1/30/23
to dj...@delorie.com
The patch inlined below (also attached for convenience) adds support for
using an exports file to dxe3gen.

The existing mechanism for exported symbols is through symbol prefixes,
i.e. the -E and -X switches, but can be really hard to use especially if
there are many symbols which don't necessarily share a common prefix, or
if some of the symbols to exclude share the common prefix with symbols
to export.

The exports file is a plain text file with one symbol name at each line,
like an exports file that can be used in macOS projects. No trailing or
leading space/tab should be used in the file. A line starting with a '#'
character is a comment line and will be ignored.

The -E and -X switches are still supported, but those two are mutually
exclusive.

Eli, Juan, DJ: Please review. OK to apply?

Index: dxe3gen.c
===================================================================
RCS file: /cvs/djgpp/djgpp/src/dxe/dxe3gen.c,v
retrieving revision 1.27
diff -u -p -r1.27 dxe3gen.c
--- djgpp/src/dxe/dxe3gen.c 28 Jan 2023 14:10:03 -0000 1.27
+++ djgpp/src/dxe/dxe3gen.c 30 Jan 2023 17:10:28 -0000
@@ -277,6 +277,9 @@ static struct
char *implib; /* name of import library */
char *dxefile; /* the name of dxe file on command line */
char *description; /* a description of the module */
+ unsigned int num_names; /* number of exported symbol names */
+ unsigned int max_names; /* maximal number of exported symbol names */
+ char **export_names; /* exported symbol names */
unsigned int num_prefix; /* number of exported prefixes */
unsigned int max_prefix; /* maximal number of exported prefixes */
char **export_prefix; /* exported symbol prefixes */
@@ -307,6 +310,9 @@ static struct
NULL,
0,
0,
+ NULL,
+ 0,
+ 0,
NULL
};

@@ -319,6 +325,8 @@ static char *dxe_ar; /* default: "ar" */
static char *dxe_ld; /* default: "ld" */
/* linker script */
static char *dxe_sc; /* default: "dxe.ld" */
+/* exports file */
+static char *expfile;


/* Desc: replaces backslash with slash in a path
@@ -422,6 +430,7 @@ static void display_help(void)
printf("-X prefix\tExclude symbols that start with <prefix> (cumulative)\n");
printf("-U\t\tAllow unresolved symbols in DXE file\n");
printf("-V\t\tVerbose output (minimal output by default)\n");
+ printf("--exports file\tExport symbols from this file (mutually
exclusive with -E/-X)\n");
printf("--show-dep\tShow dependencies for specified module\n");
printf("--show-exp\tShow symbols exported by the DXE module\n");
printf("--show-unres\tShow unresolved symbols in the DXE module\n");
@@ -465,6 +474,57 @@ static void process_env(void)
}


+/* Desc: process the exports file pointed to by --exports option.
+ *
+ * In : -
+ * Out : -
+ *
+ * Note: -
+ */
+static void process_exp_file(const char *name)
+{
+ FILE *f = fopen(name, "rb");
+ char *ptr;
+ long len;
+
+ if (!f)
+ {
+ fprintf(stderr, "Error: Couldn't open exports file %s.\n", name);
+ exit(1);
+ }
+
+ fseek(f, 0, SEEK_END);
+ len = ftell(f);
+ fseek(f, 0, SEEK_SET);
+ expfile = malloc(len + 1);
+ fread(expfile, 1, len, f);
+ fclose(f);
+ expfile[len] = '\0';
+
+ for (ptr = expfile; ; )
+ {
+ while (*ptr == '\r' || *ptr == '\n')
+ *ptr++ = '\0';
+
+ if (!*ptr) break;
+
+ if (*ptr == '#') /* comment */
+ goto loc1;
+
+ if (opt.num_names >= opt.max_names)
+ {
+ opt.max_names += 16;
+ opt.export_names = (char **)realloc(opt.export_names,
opt.max_names * sizeof(char *));
+ }
+ opt.export_names[opt.num_names++] = ptr++;
+
+ loc1:
+ while (*ptr != '\r' && *ptr != '\n')
+ ++ptr;
+ }
+}
+
+
/* Desc: process command line args
*
* In : no of arguments, argument list, ptr to store linker args
@@ -475,6 +535,7 @@ static void process_env(void)
static void process_args(int argc, char *argv[], const char *new_argv[])
{
int i, new_argc = NUMBER_OF_LINKER_ARGS;
+ int use_exports = 0;

if (!libdir)
{
@@ -482,6 +543,17 @@ static void process_args(int argc, char
exit(1);
}

+ for (i = 1; i < argc; ++i)
+ {
+ if (!strcmp(argv[i], "--exports"))
+ ++use_exports;
+ }
+ if (use_exports > 1)
+ {
+ fprintf(stderr, "Error: multiple --exports arguments not allowed.\n");
+ exit(1);
+ }
+
new_argv[0] = dxe_ld;
new_argv[1] = "-X";
new_argv[2] = "-S";
@@ -513,6 +585,11 @@ static void process_args(int argc, char
printf("Usage: %s output.dxe symbol input.o [input2.o ... -lgcc
-lc]\n", progname);
exit(-1);
}
+ if (use_exports)
+ {
+ fprintf(stderr, "Error: --exports not allowed in legacy mode.\n");
+ exit(1);
+ }

opt.max_prefix = 16;
opt.export_prefix = (char **)malloc(opt.max_prefix * sizeof(char *));
@@ -552,8 +629,13 @@ static void process_args(int argc, char
opt.implib = argv[++i];
opt.autoresolve = TRUE;
}
+ else if (!strcmp(argv[i], "--exports"))
+ {
+ process_exp_file(argv[++i]);
+ }
else if (!strcmp(argv[i], "-E"))
{
+ if (use_exports) goto bad_exports;
if (opt.num_prefix >= opt.max_prefix)
{
opt.max_prefix += 16;
@@ -563,6 +645,11 @@ static void process_args(int argc, char
}
else if (!strcmp(argv[i], "-X"))
{
+ if (use_exports)
+ { bad_exports:
+ fprintf(stderr, "Error: --exports and -E / -X options are
mutually exclusive\n");
+ exit(1);
+ }
if (opt.num_excl >= opt.max_excl)
{
opt.max_excl += 16;
@@ -1185,6 +1272,21 @@ static int write_dxe(FILE *inf, FILE *ou
continue;
}

+ if (opt.num_names)
+ {
+ BOOL ok = FALSE;
+ for (j = 0; j < opt.num_names; j++)
+ {
+ if (strcmp(opt.export_names[j], name) == 0)
+ {
+ ok = TRUE;
+ break;
+ }
+ }
+ if (!ok)
+ continue;
+ }
+
/* exported symbol */
dh.n_exp_syms++;
exports.patch

Eli Zaretskii (eliz@gnu.org) [via djgpp@delorie.com]

unread,
Jan 30, 2023, 1:06:12 PM1/30/23
to dj...@delorie.com
> From: "Ozkan Sezer (sez...@gmail.com) [via dj...@delorie.com]" <dj...@delorie.com>
> Date: Mon, 30 Jan 2023 20:27:51 +0300
>
> The patch inlined below (also attached for convenience) adds support for
> using an exports file to dxe3gen.
>
> The existing mechanism for exported symbols is through symbol prefixes,
> i.e. the -E and -X switches, but can be really hard to use especially if
> there are many symbols which don't necessarily share a common prefix, or
> if some of the symbols to exclude share the common prefix with symbols
> to export.
>
> The exports file is a plain text file with one symbol name at each line,
> like an exports file that can be used in macOS projects. No trailing or
> leading space/tab should be used in the file. A line starting with a '#'
> character is a comment line and will be ignored.
>
> The -E and -X switches are still supported, but those two are mutually
> exclusive.
>
> Eli, Juan, DJ: Please review. OK to apply?

LGTM, but why did you use binary mode for reading the exports file?

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 30, 2023, 1:23:47 PM1/30/23
to dj...@delorie.com
> LGTM,

OK, can apply tomorrow unless I get further reviews/objections.

> but why did you use binary mode for reading the exports file?

Easier forme that way -- uniform parsing across platforms.

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 31, 2023, 1:29:24 AM1/31/23
to dj...@delorie.com
Version 2 of patch attached. Changes:

- Fixes segfault if the exports file has no newline at end
- Reports missing exports in verbose mode.

For convenience, an interdiff to first version is inlined below
(cosmetic changes excluded.)

--- dxe3gen.c~
+++ dxe3gen.c
@@ -519,7 +520,7 @@
opt.export_names[opt.num_names++] = ptr++;

loc1:
- while (*ptr != '\r' && *ptr != '\n')
+ while (*ptr && *ptr != '\r' && *ptr != '\n')
++ptr;
}
}
@@ -1277,9 +1278,12 @@
BOOL ok = FALSE;
for (j = 0; j < opt.num_names; j++)
{
+ if (!opt.export_names[j])
+ continue;
if (strcmp(opt.export_names[j], name) == 0)
{
ok = TRUE;
+ opt.export_names[j] = NULL;
break;
}
}
@@ -1310,6 +1314,15 @@
}
DEBUG_PRINT_SYMBOL_TABLE_EPILOG();

+ if (opt.verbose && opt.num_names && opt.num_names != dh.n_exp_syms)
+ {
+ for (j = 0; j < opt.num_names; j++)
+ {
+ if (opt.export_names[j])
+ printf("missing export: `%s'\n", opt.export_names[j]);
+ }
+ }
+
if (errcount)
{
fclose(outf);
exports2.patch

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 31, 2023, 3:46:30 AM1/31/23
to dj...@delorie.com
Version 3 of the patch attached. Changes:

- Leading or trailing whitespace in symbol name line are now tolerated.

For convenience, an interdiff to version-2 is inlined below.

--- dxe3gen.c~
+++ dxe3gen.c
@@ -503,25 +503,28 @@ static void process_exp_file(const char

ptr = expfile;
for (;;)
{
- while (*ptr == '\r' || *ptr == '\n')
+ while (*ptr == '\r' || *ptr == '\n' || *ptr == ' ' || *ptr == '\t')
*ptr++ = '\0';

if (!*ptr) break;

if (*ptr == '#') /* comment */
- goto loc1;
+ {
+ while (*ptr && *ptr != '\r' && *ptr != '\n')
+ ++ptr;
+ continue;
+ }

if (opt.num_names >= opt.max_names)
{
opt.max_names += 16;
opt.export_names = (char **)realloc(opt.export_names,
opt.max_names * sizeof(char *));
}
opt.export_names[opt.num_names++] = ptr++;

- loc1:
- while (*ptr && *ptr != '\r' && *ptr != '\n')
+ while (*ptr && *ptr != '\r' && *ptr != '\n' && *ptr != ' ' && *ptr != '\t')
++ptr;
}
}


If you guys don't catch any gotchas, I plan to apply this 3r version to cvs.
exports3.patch

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 31, 2023, 12:58:58 PM1/31/23
to dj...@delorie.com
> If you guys don't catch any gotchas, I plan to apply this 3r version to
> cvs.

Question: Should I actually make any missing exports an error ?
Patch inlined below.

diff -up djgpp/src/dxe/dxe3gen.c~ djgpp/src/dxe/dxe3gen.c
--- djgpp/src/dxe/dxe3gen.c~
+++ djgpp/src/dxe/dxe3gen.c
@@ -1317,12 +1317,14 @@ static int write_dxe(FILE *inf, FILE *ou
}
DEBUG_PRINT_SYMBOL_TABLE_EPILOG();

- if (opt.verbose && opt.num_names && opt.num_names != dh.n_exp_syms)
+ if (opt.num_names && opt.num_names != dh.n_exp_syms)
{
+ errcount = opt.num_names - dh.n_exp_syms;
+ fprintf(stderr, "Error: %d symbols to be exported are
missing:\n", errcount);
for (j = 0; j < opt.num_names; j++)
{
if (opt.export_names[j])
- printf("missing export: `%s'\n", opt.export_names[j]);
+ fprintf(stderr, "missing export: `%s'\n", opt.export_names[j]);
}
}

Eli Zaretskii (eliz@gnu.org) [via djgpp@delorie.com]

unread,
Jan 31, 2023, 1:48:08 PM1/31/23
to dj...@delorie.com
> From: "Ozkan Sezer (sez...@gmail.com) [via dj...@delorie.com]" <dj...@delorie.com>
> Date: Tue, 31 Jan 2023 20:55:31 +0300
>
> > If you guys don't catch any gotchas, I plan to apply this 3r version to
> > cvs.
>
> Question: Should I actually make any missing exports an error ?
> Patch inlined below.

Unless this is a real problem, I'd say do this only under the verbose
operation, i.e. optionally.

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 31, 2023, 2:13:49 PM1/31/23
to dj...@delorie.com
> Question: Should I actually make any missing exports an error ?
> Patch inlined below.

> Unless this is a real problem,

It is not,

> I'd say do this only under the verbose operation, i.e. optionally.

i.e. error out only in verbose mode, which _can_ lead to problems?
I' suggest inventing a new switch like --nomissing, what do you think?

Eli Zaretskii (eliz@gnu.org) [via djgpp@delorie.com]

unread,
Jan 31, 2023, 2:37:08 PM1/31/23
to dj...@delorie.com
> From: "Ozkan Sezer (sez...@gmail.com) [via dj...@delorie.com]" <dj...@delorie.com>
> Date: Tue, 31 Jan 2023 22:10:28 +0300
>
> > I'd say do this only under the verbose operation, i.e. optionally.
>
> i.e. error out only in verbose mode, which _can_ lead to problems?
> I' suggest inventing a new switch like --nomissing, what do you think?

SGTM.

Ozkan Sezer (sezeroz@gmail.com) [via djgpp@delorie.com]

unread,
Jan 31, 2023, 3:19:35 PM1/31/23
to dj...@delorie.com
On 1/31/23, Eli Zaretskii (el...@gnu.org) [via dj...@delorie.com]
OK, the patch is applied to cvs as r1.28:
https://www.delorie.com/bin/cvsweb.cgi/djgpp/src/dxe/dxe3gen.c
https://www.delorie.com/bin/cvsweb.cgi/djgpp/src/dxe/dxe3gen.c.diff?r1=1.27&r2=1.28

Documentation and 2.06 changelog updates are TODO (unless someone beats
me to it.)
0 new messages