Skip to content

Commit

Permalink
api(Windows): Remove the ordinals attached to exported functions
Browse files Browse the repository at this point in the history
In order to make ABI compatibility guarantees about the Windows DLL,
we had to keep maintaining the API ordinals consistently. As we are
now designing a fresh new ABI, we use this opportunity to stop using
ordinals altogether.

Exporting API functions by ordinal numbers instead of names was a
necessity in the early (16-bit) versions of Windows, by design, to
minimize the memory requirements. Although using ordinals was still
possible in all subsequent versions of Windows, it was no longer
necessary from the 32-bit versions of Windows onwards.

The libpng DLL will still have ordinals, assigned arbitrarily, but
the dynamic linking of applications to this DLL will be done by name.
(The applications that use the zlib DLL operate in the same manner.)

Reviewed-by: John Bowler <jbowler@acm.org>
Signed-off-by: Cosmin Truta <ctruta@gmail.com>
  • Loading branch information
ctruta committed Feb 1, 2025
1 parent 363aa62 commit c4780f3
Show file tree
Hide file tree
Showing 9 changed files with 565 additions and 676 deletions.
536 changes: 262 additions & 274 deletions png.h

Large diffs are not rendered by default.

22 changes: 7 additions & 15 deletions pngconf.h
Original file line number Diff line number Diff line change
Expand Up @@ -290,13 +290,8 @@
# define PNG_EXPORT_TYPE(type) PNG_IMPEXP type
#endif

/* The ordinal value is only relevant when preprocessing png.h for symbol
* table entries, so we discard it here. See the .dfn files in the
* scripts directory.
*/

#ifndef PNG_EXPORTA
# define PNG_EXPORTA(ordinal, type, name, args, attributes) \
# define PNG_EXPORTA(type, name, args, attributes) \
PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), args, \
PNG_LINKAGE_API attributes)
#endif
Expand All @@ -306,12 +301,11 @@
*/
#define PNG_EMPTY /*empty list*/

#define PNG_EXPORT(ordinal, type, name, args) \
PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY)
#define PNG_EXPORT(type, name, args) PNG_EXPORTA(type, name, args, PNG_EMPTY)

/* Use PNG_REMOVED to comment out a removed interface. */
#ifndef PNG_REMOVED
# define PNG_REMOVED(ordinal, type, name, args, attributes)
# define PNG_REMOVED(type, name, args, attributes)
#endif

#ifndef PNG_CALLBACK
Expand Down Expand Up @@ -446,18 +440,16 @@

#ifndef PNG_FP_EXPORT /* A floating point API. */
# ifdef PNG_FLOATING_POINT_SUPPORTED
# define PNG_FP_EXPORT(ordinal, type, name, args)\
PNG_EXPORT(ordinal, type, name, args);
# define PNG_FP_EXPORT(type, name, args) PNG_EXPORT(type, name, args);
# else /* No floating point APIs */
# define PNG_FP_EXPORT(ordinal, type, name, args)
# define PNG_FP_EXPORT(type, name, args)
# endif
#endif
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
# ifdef PNG_FIXED_POINT_SUPPORTED
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
PNG_EXPORT(ordinal, type, name, args);
# define PNG_FIXED_EXPORT(type, name, args) PNG_EXPORT(type, name, args);
# else /* No fixed point APIs */
# define PNG_FIXED_EXPORT(ordinal, type, name, args)
# define PNG_FIXED_EXPORT(type, name, args)
# endif
#endif

Expand Down
6 changes: 3 additions & 3 deletions pngpriv.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* pngpriv.h - private declarations for use inside libpng
*
* Copyright (c) 2018-2024 Cosmin Truta
* Copyright (c) 2018-2025 Cosmin Truta
* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
* Copyright (c) 1996-1997 Andreas Dilger
* Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
Expand Down Expand Up @@ -185,7 +185,7 @@
*/
#ifndef PNG_FP_EXPORT
# ifndef PNG_FLOATING_POINT_SUPPORTED
# define PNG_FP_EXPORT(ordinal, type, name, args)\
# define PNG_FP_EXPORT(type, name, args)\
PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
# ifndef PNG_VERSION_INFO_ONLY
typedef struct png_incomplete png_double;
Expand All @@ -197,7 +197,7 @@
#endif
#ifndef PNG_FIXED_EXPORT
# ifndef PNG_FIXED_POINT_SUPPORTED
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
# define PNG_FIXED_EXPORT(type, name, args)\
PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
# endif
#endif
Expand Down
155 changes: 33 additions & 122 deletions scripts/checksym.awk
Original file line number Diff line number Diff line change
Expand Up @@ -17,40 +17,19 @@
BEGIN {
err = 0
master = "" # master file
official[1] = "" # defined symbols from master file
symbol[1] = "" # defined symbols from png.h
removed[1] = "" # removed symbols from png.h
lasto = 0 # last ordinal value from png.h
mastero = 0 # highest ordinal in master file
symbolo = 0 # highest ordinal in png.h
official[""] = "" # defined symbols from master file
symbol[""] = "" # defined symbols from png.h
removed[""] = "" # removed symbols from png.h
missing = "error" # log an error on missing symbols
of = "symbols.new" # default to a fixed name
}

# Read existing definitions from the master file (the first
# file on the command line.) This must be a def file and it
# has definition lines (others are ignored) of the form:
#
# symbol @ordinal
#
# file on the command line.) This is a Windows .def file
# which must NOT have definitions of the form "symbol @ordinal".
master == "" {
master = FILENAME
}
FILENAME == master && NF == 2 && $2 ~ /^@/ && $1 !~ /^;/ {
o = 0 + substr($2, 2)
if (o > 0) {
if (official[o] == "") {
official[o] = $1
if (o > mastero) mastero = o
next
} else {
print master ": duplicated symbol:", official[o] ":", $0
}
} else {
print master ": bad export line format:", $0
}
err = 1
}
FILENAME == master && $1 == ";missing" && NF == 2 {
# This allows the master file to control how missing symbols
# are handled; symbols that aren't in either the master or
Expand All @@ -65,64 +44,33 @@ FILENAME == master {
# Read new definitions, these are free form but the lines must
# just be symbol definitions. Lines will be commented out for
# 'removed' symbols, introduced in png.h using PNG_REMOVED rather
# than PNG_EXPORT. Use symbols.dfn or pngwin.dfn to generate the
# input file.
# than PNG_EXPORT. Use symbols.dfn to generate the input file.
#
# symbol @ordinal # two fields, exported symbol
# ; symbol @ordinal # three fields, removed symbol
# ; @ordinal # two fields, the last ordinal
NF == 2 && $1 == ";" && $2 ~ /^@[1-9][0-9]*$/ {
# last ordinal
o = 0 + substr($2, 2)
if (lasto == 0 || lasto == o) {
lasto = o
} else {
print "png.h: duplicated last ordinal:", lasto, o
err = 1
}
# symbol # one field, exported symbol
# ; symbol # two fields, removed symbol
#
NF == 0 {
# empty line
next
}
NF == 3 && $1 == ";" && $3 ~ /^@[1-9][0-9]*$/ {
# removed symbol
o = 0 + substr($3, 2)
if (removed[o] == "" || removed[o] == $2) {
removed[o] = $2
if (o > symbolo) symbolo = o
} else {
print "png.h: duplicated removed symbol", o ": '" removed[o] "' != '" $2 "'"
err = 1
}
NF == 1 && $1 ~ /^[A-Za-z_][A-Za-z_0-9]*$/ {
# exported symbol (one field)
symbol[$1] = $1
next
}
NF == 2 && $2 ~ /^@[1-9][0-9]*$/ {
# exported symbol
o = 0 + substr($2, 2)
if (symbol[o] == "" || symbol[o] == $1) {
symbol[o] = $1
if (o > symbolo) symbolo = o
} else {
print "png.h: duplicated symbol", o ": '" symbol[o] "' != '" $1 "'"
err = 1
}
NF == 2 && $1 == ";" && $2 ~ /^[A-Za-z_][A-Za-z_0-9]*$/ {
# removed symbol (two fields)
removed[$1] = $1
next
}
{
next # skip all other lines
print "error: invalid line:", $0
err = 1
next
}

# At the end check for symbols marked as both duplicated and removed
END {
if (symbolo > lasto) {
print "highest symbol ordinal in png.h,",
symbolo ", exceeds last ordinal from png.h", lasto
err = 1
}
if (mastero > lasto) {
print "highest symbol ordinal in", master ",",
mastero ", exceeds last ordinal from png.h", lasto
err = 1
}
unexported = 0
# Add a standard header to symbols.new:
# Write the standard header to "symbols.new":
print ";Version INSERT-VERSION-HERE" >of
print ";--------------------------------------------------------------" >of
print "; LIBPNG symbol list as a Win32 DEF file" >of
Expand All @@ -132,59 +80,22 @@ END {
print "" >of
print "EXPORTS" >of

for (o = 1; o <= lasto; ++o) {
if (symbol[o] == "" && removed[o] == "") {
if (unexported == 0) unexported = o
if (official[o] == "") {
# missing in export list too, so ok
if (o < lasto) continue
}
}
if (unexported != 0) {
# Symbols in the .def but not in the new file are errors, but
# the 'unexported' symbols aren't in either. By default this
# is an error too (see the setting of 'missing' at the start),
# but this can be reset on the command line or by stuff in the
# file - see the comments above.
if (missing != "ignore") {
if (o - 1 > unexported) {
print "png.h:", missing ": missing symbols:", unexported "-" o - 1
} else {
print "png.h:", missing ": missing symbol:", unexported
}
if (missing != "warning") {
err = 1
}
}
unexported = 0
}
if (symbol[o] != "" && removed[o] != "") {
print "png.h: symbol", o,
"both exported as '" symbol[o] "' and removed as '" removed[o] "'"
err = 1
} else if (symbol[o] != official[o]) {
# either the symbol is missing somewhere or it changed
err = 1
if (symbol[o] == "") {
print "png.h: symbol", o,
"is exported as '" official[o] "' in", master
} else if (official[o] == "") {
print "png.h: exported symbol", o,
"'" symbol[o] "' not present in", master
} else {
print "png.h: exported symbol", o,
"'" symbol[o] "' exists as '" official[o] "' in", master
}
}
# Collect all unique symbols into a plain array for sorting.
i = 1
for (sym in symbol) {
if (sym != "") sorted_symbols[i++] = sym
}

# Finally generate symbols.new
if (symbol[o] != "") {
print " " symbol[o], "@" o > of
}
# Sort and print the symbols.
asort(sorted_symbols)
for (i = 1; i <= length(sorted_symbols); i++) {
print " " sorted_symbols[i] >of
}

if (err != 0) {
print "*** A new list is in", of, "***"
exit 1
}

# TODO: Check for symbols that are both defined and removed.
}
2 changes: 1 addition & 1 deletion scripts/prefix.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* and license in png.h
*/

#define PNG_EXPORTA(ordinal, type, name, args, attributes)\
#define PNG_EXPORTA(type, name, args, attributes)\
PNG_DFN "@" name "@"

/* The configuration information *before* the additional of symbol renames,
Expand Down
2 changes: 1 addition & 1 deletion scripts/sym.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* and license in png.h
*/

#define PNG_EXPORTA(ordinal, type, name, args, attributes)\
#define PNG_EXPORTA(type, name, args, attributes)\
PNG_DFN "@" SYMBOL_PREFIX "@@" name "@"

#include "../png.h"
10 changes: 4 additions & 6 deletions scripts/symbols.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,10 @@
* scripts/pnglibconf.dfa then this checks the .dfa file too.
*/

#define PNG_EXPORTA(ordinal, type, name, args, attributes)\
PNG_DFN "@" name "@ @@" ordinal "@"
#define PNG_REMOVED(ordinal, type, name, args, attributes)\
PNG_DFN "; @" name "@ @@" ordinal "@"
#define PNG_EXPORT_LAST_ORDINAL(ordinal)\
PNG_DFN "; @@" ordinal "@"
#define PNG_EXPORTA(type, name, args, attributes)\
PNG_DFN "@" name "@"
#define PNG_REMOVED(type, name, args, attributes)\
PNG_DFN "; @" name "@"

/* Read the defaults, but use scripts/pnglibconf.h.prebuilt; the 'standard'
* header file.
Expand Down
Loading

0 comments on commit c4780f3

Please sign in to comment.