Skip to content

Commit

Permalink
Merge pull request ziglang#15101 from motiejus/glibc_compat
Browse files Browse the repository at this point in the history
glibc: add backwards compatibility for some symbols
  • Loading branch information
andrewrk authored Apr 6, 2023
2 parents 9f95718 + 652e8cf commit 13aa787
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 0 deletions.
8 changes: 8 additions & 0 deletions lib/libc/glibc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
glibc headers are slightly patched for backwards compatibility. This is not
good, because it requires to maintain our patchset whlist upgrading glibc.

Until universal headers are real and this file can be removed, these commits
need to be cherry-picked in the future glibc header upgrades:

- 39083c31a550ed80f369f60d35791e98904b8096
- a89813ef282c092a9caf699731c7faaf485acabe
7 changes: 7 additions & 0 deletions lib/libc/glibc/io/fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ typedef __pid_t pid_t;
effective IDs, not real IDs. */
#endif


/* fcntl was a simple symbol until glibc 2.27 inclusive. glibc 2.28 onwards
* re-defines it to fcntl64 (via #define) if _FILE_OFFSET_BITS == 64. */
#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 28) || __GLIBC__ > 2
/* Do the file control operation described by CMD on FD.
The remaining arguments are interpreted depending on CMD.
Expand Down Expand Up @@ -197,6 +201,9 @@ extern int __fcntl_time64 (int __fd, int __request, ...) __THROW;
# define fcntl __fcntl_time64
# endif
#endif
#else /* glibc 2.27 or lower */
extern int fcntl (int __fd, int __cmd, ...);
#endif

/* Open FILE and return a new file descriptor for it, or -1 on error.
OFLAG determines the type of access used. If O_CREAT or O_TMPFILE is set
Expand Down
8 changes: 8 additions & 0 deletions lib/libc/include/generic-glibc/fcntl.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ typedef __pid_t pid_t;
effective IDs, not real IDs. */
#endif


/* fcntl was a simple symbol until glibc 2.27 inclusive.
* glibc 2.28 onwards converted it to a macro when compiled with
* USE_LARGEFILE64. */
#if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 28) || __GLIBC__ > 2
/* Do the file control operation described by CMD on FD.
The remaining arguments are interpreted depending on CMD.
Expand Down Expand Up @@ -197,6 +202,9 @@ extern int __fcntl_time64 (int __fd, int __request, ...) __THROW;
# define fcntl __fcntl_time64
# endif
#endif
#else /* glibc 2.27 or lower */
extern int fcntl (int __fd, int __cmd, ...);
#endif

/* Open FILE and return a new file descriptor for it, or -1 on error.
OFLAG determines the type of access used. If O_CREAT or O_TMPFILE is set
Expand Down
22 changes: 22 additions & 0 deletions lib/libc/include/generic-glibc/resolv.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,28 @@ __END_DECLS
#define res_init __res_init
#define res_isourserver __res_isourserver

/* In glibc 2.33 and earlier res_search, res_nsearch, res_query, res_nquery,
* res_querydomain, res_nquerydomain were #define'd to __res_search,
* __res_nsearch, etc. glibc 2.34 onwards removes the macros and exposes the
* symbols directly. New glibc exposes compat symbols with underscores for
* backwards compatibility. Applications linked to glibc 2.34+ are expected
* to use the non-underscored symbols.
*
* It will be enough to bring the macros back when compiling against the older
* glibc versions.
*
* See glibc commit ea9878ec271c791880fcbbe519d70c42f8113750.
*/
#if (__GLIBC__ == 2 && __GLIBC_MINOR__ < 34)
#define res_search __res_search
#define res_nsearch __res_nsearch
#define res_query __res_query
#define res_nquery __res_nquery
#define res_querydomain __res_querydomain
#define res_nquerydomain __res_nquerydomain
#endif
/* end glibc compat hacks */

#ifdef _LIBC
# define __RESOLV_DEPRECATED
# define __RESOLV_DEPRECATED_MSG(msg)
Expand Down
4 changes: 4 additions & 0 deletions test/link.zig
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ pub const cases = [_]Case{
.build_root = "test/link/interdependent_static_c_libs",
.import = @import("link/interdependent_static_c_libs/build.zig"),
},
.{
.build_root = "test/link/glibc_compat",
.import = @import("link/glibc_compat/build.zig"),
},

// WASM Cases
.{
Expand Down
18 changes: 18 additions & 0 deletions test/link/glibc_compat/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
const std = @import("std");

pub fn build(b: *std.Build) void {
const test_step = b.step("test", "Test");
b.default_step = test_step;

inline for (.{ "aarch64-linux-gnu.2.27", "aarch64-linux-gnu.2.34" }) |t| {
const exe = b.addExecutable(.{
.name = t,
.root_source_file = .{ .path = "main.c" },
.target = std.zig.CrossTarget.parse(
.{ .arch_os_abi = t },
) catch unreachable,
});
exe.linkLibC();
test_step.dependOn(&exe.step);
}
}
37 changes: 37 additions & 0 deletions test/link/glibc_compat/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#define _FILE_OFFSET_BITS 64
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <resolv.h>

int main() {
/* in glibc 2.28+ and _FILE_OFFSET_BITS=64 fcntl is #define'd to fcntl64
* Thus headers say `fcntl64` exists, but libc.so.6 (the old one)
* disagrees, resulting in a linking error unless headers are made
* backwards-compatible.
*
* Glibc 2.28+:
* FUNC GLOBAL DEFAULT UND fcntl64@GLIBC_2.28 (3):
*
* Glibc 2.27 or older:
* FUNC GLOBAL DEFAULT UND fcntl@GLIBC_2.2.5
*/
printf("address to fcntl: %p\n", fcntl);

/* The following functions became symbols of their own right with glibc
* 2.34+. Before 2.34 resolv.h would #define res_search __res_search; and
* __res_search is a valid symbol since the beginning of time.
*
* On glibc 2.34+ these symbols are linked this way:
* FUNC GLOBAL DEFAULT UND res_search@GLIBC_2.34 (2)
*
* Pre-glibc 2.34:
* FUNC GLOBAL DEFAULT UND __res_search@GLIBC_2.2.5 (4)
*/
printf("address to res_search: %p\n", res_search);
printf("address to res_nsearch: %p\n", res_nsearch);
printf("address to res_query: %p\n", res_query);
printf("address to res_nquery: %p\n", res_nquery);
printf("address to res_querydomain: %p\n", res_querydomain);
printf("address to res_nquerydomain: %p\n", res_nquerydomain);
}

0 comments on commit 13aa787

Please sign in to comment.