1

I have a 3rd party C static library that uses xdr_wrapstring. I am moving to RH 8 where these symbols are not unavailable in the default /lib64/libc.so.6, but are available as versioned symbols (xdr_wrapstring@GLIBC_2.2.5)? Is there a way to tell the linker to resolve xdr_wrapstring to xdr_wrapstring@GLIBC_2.2.5?

I can't link with libtirpc (which provides unversioned symbols) due to it requiring libssl.so & libcrypto.so via libk5crypto.so

zrb
  • 851
  • 7
  • 16
  • 1
    Who says Linux doesn't have its own version of DLL hell ? :-) – Steve Friedl Jan 05 '23 at 16:08
  • One way is to use a `.s` assembler stub (e.g.) `xdrfix.s`: `.globl xdr_wrapstring xdr_wrapstring: jmp xdr_wrapstring@GLIBC_2.2.5` Build with: `as -c xdrfix.s` Then, link the program with `xdrfix.o` – Craig Estey Jan 05 '23 at 16:37
  • Thanks Craig. However, that gives the error "junk `@GLIBC_2.2.5' after expression". But seems like a good solution otherwise – zrb Jan 05 '23 at 16:50

1 Answers1

0

Prefaced by the top comments ...

The assembler .symver shows some promise. A web search on it shows:

  1. http://web.mit.edu/rhel-doc/3/rhel-as-en-3/symver.html
  2. https://man7.org/conf/lca2006/shared_libraries/slide19a.html
  3. Linking against older symbol version in a .so file

From this, I've created a symver.s file that has stubs that seems to work on my system [which has the same versioned symbols issue].

However, I'd have a look at those linked pages (e.g.) symver is also an attribute, so it may be possible to do this with inline asm from a .c file.


I've created a crude test program:

// xdrtest.c -- print address of xdr_wrapstring

#include <stdio.h>

void xdr_wrapstring(void);

int
main(void)
{
    void *ptr = xdr_wrapstring;
    printf("%p\n",ptr);
    return 0;
}

Here is an better test program:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>

#include <rpc/types.h>
#include <rpc/xdr.h>

#define ALEN    1000

#define sysfault(_fmt...) \
    do { \
        fprintf(stderr,_fmt); \
        exit(1); \
    } while (0)

XDR xdrs;

void
sendstring(const char *str)
{
    static char buf[ALEN];
    char *bp;

    strcpy(buf,str);

    bp = buf;

    if (! xdr_wrapstring(&xdrs,&bp))
        sysfault("sendstring: xdr_wrapstring fail -- str='%s' buf='%s'\n",
            str,buf);
}

void
recvstring(const char *str)
{
    static char buf[ALEN];
    char *bp;

    bp = buf;

    if (! xdr_wrapstring(&xdrs,&bp))
        sysfault("recvstring: xdr_wrapstring fail -- str='%s' buf='%s'\n",
            str,buf);

    fprintf(stderr,"buf=%p bp=%p str='%s' bp='%s'\n",buf,bp,str,bp);

    if (strcmp(bp,str) != 0)
        sysfault("recvstring: MISMATCH\n");
}

void
writer(void)
{

    xdrstdio_create(&xdrs, stdout, XDR_ENCODE);

    sendstring("hello");
    sendstring("world");
    sendstring("goodbye");
    sendstring("galaxy");
}

void
reader(void)
{

    xdrstdio_create(&xdrs, stdin, XDR_DECODE);

    recvstring("hello");
    recvstring("world");
    recvstring("goodbye");
    recvstring("galaxy");
}

int
main(int argc,char **argv)
{
    int opt_dir = -1;

    --argc;
    ++argv;

    for (;  argc > 0;  --argc, ++argv) {
        char *cp = *argv;
        if (*cp != '-')
            break;

        cp += 2;
        switch (cp[-1]) {
        case 'r':
            opt_dir = 0;
            break;
        case 'w':
            opt_dir = 1;
            break;
        }
    }

    switch (opt_dir) {
    case 0:
        reader();
        break;
    case 1:
        writer();
        break;
    default:
        sysfault("main: -r/-w not specified\n");
        break;
    }

    return 0;
}

Here is the "magic" xdrver.s file:

    .globl xdrstdio_create
    .symver foo, xdrstdio_create@GLIBC_2.2.5
xdrstdio_create:
    jmp foo

    .globl xdr_wrapstring
    .symver bar, xdr_wrapstring@GLIBC_2.2.5
xdr_wrapstring:
    jmp bar

Compile with (e.g.):

cc -o xdrtest xdrtest.c xdrver.s

Or, of course, we can create xdrver.o and link with whatever program we want.

Anyway, to test the program:

./xdrtest -w | ./xdrtest -r

And, the output is:

buf=0x4044a0 bp=0x4044a0 str='hello' bp='hello'
buf=0x4044a0 bp=0x4044a0 str='world' bp='world'
buf=0x4044a0 bp=0x4044a0 str='goodbye' bp='goodbye'
buf=0x4044a0 bp=0x4044a0 str='galaxy' bp='galaxy'
Craig Estey
  • 30,627
  • 4
  • 24
  • 48