momo zone

调核人的blog

[转载]Linking to Older Versioned Symbols (glibc)

转载自http://www.trevorpounds.com/blog/?p=103

In my last post I gave a brief overview of the mechanism used internally by glibc for versioning symbols within shared libraries. As an addendum to my previous article I would like to discuss a simple way to force linking against older glibc symbols. Why would you do this you may ask? Well, suppose you have several GNU/Linux systems with varying glibc installs across them but you want to deliver a binary that would be compatible across them. One option is to statically link your binary, my vote :) , the other is to link to an older symbol within the shared library. I would like to mention that using an older symbol has the obvious drawback, possible advantage, of using something that was deprecated for a reason in the past (i.e. broken, behavior changes, performed poorly, new arch support, etc.). The reason I say it is possibly advantageous to link against an older symbol may be because it is known to behave in a desired way, broken or not! I present the following merely for education purposes, so use with care.

To force linking against a particular symbol you need to use the same .symver pseudo-op that is used for defining versioned symbols in the first place. In the following example I make use of glibc’s realpath, but want to make sure it is linked against an older 2.2.5 version.

#include <limits.h>
#include <stdlib.h>
#include <stdio.h>
 
__asm__(".symver realpath,realpath@GLIBC_2.2.5");
int main()
{
   char* unresolved = "/lib64";
   char  resolved[PATH_MAX+1];
 
   if(!realpath(unresolved, resolved))
      { return 1; }
 
   printf("%s\n", resolved);
 
   return 0;
}

If you were to use objdump on the resulting binary you would see that it is indeed using realpath@GLIBC_2.2.5! Also note that other symbols have been resolved to their defaults so you need to make sure you add a .symver pseudo-op for each symbol you want to force to an older version.

0000000000000000      F *UND*  0000000000000000         realpath@GLIBC_2.2.5
...
0000000000000000      F *UND*  0000000000000000         __stack_chk_fail@@GLIBC_2.4

The .symver pseudo-op can be used this way to force any symbol to be linked against an older one so long as it is valid. To ease linking against older glibc versions I’ve provided a simple header which can be used to force linking against the minimum glibc version for a give x86 architecture. The minimum versions I am using were taken fromshlib-versions file of the glibc git tree.

#ifndef __GLIBC_COMPAT_SYMBOL_H__
#define __GLIBC_COMPAT_SYMBOL_H__ 1
 
/**
 * add other architecures below
 */
#ifdef __amd64__
   #define GLIBC_COMPAT_SYMBOL(FFF) __asm__(".symver " #FFF "," #FFF "@GLIBC_2.2.5");
#else
   #define GLIBC_COMPAT_SYMBOL(FFF) __asm__(".symver " #FFF "," #FFF "@GLIBC_2.0");
#endif /*__amd64__*/
 
#endif /*__GLIBC_COMPAT_SYMBOL_H__*/

To use the glibc compatible header with the realpath example above, we merely use the GLIBC_COMPAT_SYMBOL macro with the appropriate symbol:

GLIBC_COMPAT_SYMBOL(realpath)

 

Advertisements

发表评论

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / 更改 )

Twitter picture

You are commenting using your Twitter account. Log Out / 更改 )

Facebook photo

You are commenting using your Facebook account. Log Out / 更改 )

Google+ photo

You are commenting using your Google+ account. Log Out / 更改 )

Connecting to %s

%d 博主赞过: