LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 11-18-2004, 10:40 PM   #1
Damaged Soul
LQ Newbie
 
Registered: Nov 2004
Posts: 8

Rep: Reputation: 0
Getting Base Address of Dynamic Library


This seems like a simple problem, but being that's it's my first time coding for Linux, it's not. I'm not a complete newbie to C/C++ coding. Just trying to learn to deal with Linux as I've been coding for ONLY Windows for awhile.

All I'm trying to do is get the base memory address of a dynamic library loaded in memory. Since LoadLibrary in Windows returns this, I figured dlopen would do the same since it too returns a void pointer. But as I soon found out with this code, I was wrong about that:

Code:
#ifdef __linux__
	gameDllAddress = (unsigned long)dlopen(GAMEDLL_NAME, RTLD_NOW);
#else
	gameDllAddress = (unsigned long)LoadLibrary(GAMEDLL_NAME);
#endif
With this I got a segmentation fault and an error about not having access to a memory location when I tried to read a particular byte in memory using that as a base address.

Someone else mentioned to me about the use of dladdr and using Dl_info struct to get the base address. I too have tried this. Maybe I'm going about this the wrong way, but I'm not sure:

Code:
#ifdef __linux__
	Dl_info gameDllInfo;
	dladdr(&MDLL_Spawn, &gameDllInfo);
	gameDllAddress = (unsigned long)gameDllInfo.dli_fbase;
#else
	gameDllAddress = (unsigned long)LoadLibrary(GAMEDLL_NAME);
#endif
GAMEDLL_NAME is defined elsewhere with the name of the dynamic library I'm loading and gameDllAddress is obviously an unsigned long that is declared elsewhere. MDLL_Spawn is a function I have access to (which is not in the code I'm writing) and since dladdr requires a function pointer as an address this what I have used. The problem here though is odd. I do not get a seg fault anymore when reading memory, but I noticed that if I read one memory location as a Dword (long) I would get one value. If I moved 4 bytes up, I'd get the same value. Then I moved another 4 bytes and I'd still get the same value returned. And I know that looking through a hex editor at the DLL I'm loading, it doesn't have 3 Dwords in a row with the same value.

So I'm guessing the way I got the base address is incorrect here. If not, then perhaps the value I'm trying to read has been relocated and is not in the same offset as it would be if I looked at the DLL I'm loading in a hex editor. If that is the case, then what's the best way to deal with this? I might add that my code works fine in Windows and it's not relocating anything. But I'm unsure of the exact details of how Linux manages memory and such, so I certainly might have missed something here.

Help with this would be much appreciated.

Last edited by Damaged Soul; 11-18-2004 at 10:47 PM.
 
Old 11-19-2004, 11:52 AM   #2
jim mcnamara
Member
 
Registered: May 2002
Posts: 964

Rep: Reputation: 34
You are not dealing with dll's in Linux. Each object in a shared library has it's own address. dll's use a function vector table at the beginning (vtable) as an array of function pointers with offsets.

Unix loads a library, dlopen() then calls dlsym() to get the entry point of one routine.

What are you doing with the base address? It may be meaningless for linux unless you build an array of offsets or something.

try man dlsym
 
Old 11-19-2004, 12:09 PM   #3
Damaged Soul
LQ Newbie
 
Registered: Nov 2004
Posts: 8

Original Poster
Rep: Reputation: 0
Hmm, alright will look at using dlsym. But this does kind of make things a bit more difficult. Anyways, what I am trying to do with the base address is this... Let's say I look at a binary SO file in a hex editor of some sort. There is a particular value that I want to read (as well as modify later), so I use this hex editor to derive an offset. So I was thinking that I could just use the base address + the offset I derived to get the memory address of the value I want to retrieve. This logic works in a Windows environment, but apparently not in Linux. The binary SO file isn't loaded as a whole somewhere in memory then, I'm guessing, but rather as individual objects?
 
Old 11-19-2004, 12:53 PM   #4
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 58
Only symbols required by the program are loaded into memory. Anything more would just be a waste of resources and time.

I'm not quite sure what you're trying to do with the .so file. Are you sure you don't just want to link it with the executable instead of loading it manually at runtime?
 
Old 11-19-2004, 01:19 PM   #5
Damaged Soul
LQ Newbie
 
Registered: Nov 2004
Posts: 8

Original Poster
Rep: Reputation: 0
Well honestly, the SO is already loaded into memory at the time my code is running. In Windows using LoadLibrary would return the base address of the already loaded DLL. What I'm doing is a bit of hack work I guess. I could go ahead and modify the SO manually in a hex editor and achieve what I want, but I'd really like to do this memory. But in Linux this seems to be more difficult than it does in Windows. I guess I just need to rethink how I'm going to do this, because my "Windows logic" isn't going to work here.
 
Old 11-19-2004, 01:34 PM   #6
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 58
I'm still not sure what you're goal is. You can mmap() the .so file if you want a copy of it in memory.
 
Old 11-19-2004, 02:01 PM   #7
jim mcnamara
Member
 
Registered: May 2002
Posts: 964

Rep: Reputation: 34
Sounds like he is modfying a global value that the routines in the library use.

Th eOP may want to look at shmat() or mmap();
 
Old 11-19-2004, 02:52 PM   #8
itsme86
Senior Member
 
Registered: Jan 2004
Location: Oregon, USA
Distribution: Slackware
Posts: 1,246

Rep: Reputation: 58
Well, that's not difficult to do if you only want to change for that instance. For example:
Code:
itsme@itsme:~/C$ cat dltest.c
#include <stdio.h>
#include <stdlib.h>
#include <dlfcn.h>

int main(void)
{
  void *handle;
  int *numptr;
  void (*func)();

  handle = dlopen("./dltest2.so", RTLD_LAZY);
  numptr = dlsym(handle, "num");
  func = dlsym(handle, "printnum");

  func();
  *numptr = 86;
  func();

  dlclose(handle);
  return EXIT_SUCCESS;
}
Code:
itsme@itsme:~/C$ cat dltest2.c
#include <stdio.h>

int num = 3;

void printnum(void)
{
  printf("num = %d\n", num);
}
Code:
itsme@itsme:~/C$ gcc -Wall -rdynamic dltest.c -o dltest -ldl
itsme@itsme:~/C$ gcc -Wall -shared dltest2.c -o dltest2.so
itsme@itsme:~/C$ ./dltest
num = 3
num = 86
So you can see that num in the .so file is being modified.

Last edited by itsme86; 11-19-2004 at 03:02 PM.
 
Old 10-06-2006, 05:50 AM   #9
pagg
LQ Newbie
 
Registered: Oct 2006
Location: Minsk
Distribution: ~
Posts: 1

Rep: Reputation: 0
Question

Hi, all

I have the same problem as poster, I think. That is I need to modify global variable declared in libnotmy.so at runtime. But the problem is not solved by last post of itsme86.
This is because of the following:

>nm: libnotmy.so: no symbols

So I cannot modify that variable by symbol name nor can I calculate offset from any other defined symbol, cause there are no symbols exported, as you see.
The only thing I can try here (and it is indeed works on Windows) is somehow to get libnotmy.so's base load address at runtime.

Is this possible?
 
Old 10-07-2006, 04:27 AM   #10
primo
Member
 
Registered: Jun 2005
Posts: 542

Rep: Reputation: 34
Maybe reading "/proc/self/maps" can help you. Its format is explained in proc(5) - run "man 5 proc". You will notice these mappings having permissions (like disabling write access to prevent buffer overflows that overwrite data and instructions inside). You may use mprotect(2) to assign new permissions.

I tried itsme86's example on a Linux 2.6.11 and it worked but it segfaulted on FreeBSD. Would it work on SELinux ? Maybe permissions will help solve that.
 
Old 12-13-2010, 08:33 AM   #11
ium
LQ Newbie
 
Registered: Dec 2010
Posts: 1

Rep: Reputation: 0
How to get the address, which a library has been loaded to?

After some research I managed to find out the method of discovering the address of the library loading by its descriptor, which is returned by the dlopen() function. It is performed with the help of such macro:

#define LIBRARY_ADDRESS_BY_HANDLE(dlhandle) ((NULL == dlhandle) ? NULL : (void*)*(size_t const*)(dlhandle))
 
Old 12-13-2010, 01:28 PM   #12
TimothyEBaldwin
Member
 
Registered: Mar 2009
Posts: 249

Rep: Reputation: 27
Quote:
Originally Posted by pagg View Post
This is because of the following:

>nm: libnotmy.so: no symbols
You need to use the -D option for nm to see the symbols.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
error loading dynamic library with Java trutnev Programming 4 06-01-2005 03:33 PM
PHP Warning: Unable to load dynamic library xbaez Linux - Software 3 02-15-2005 06:11 PM
base address and port address Nodren Linux - Hardware 0 08-30-2004 02:54 PM
Fix ip address vs Dynamic ip address yenonn Linux - Networking 5 04-13-2004 07:25 AM
dynamic library versioning kev82 Linux - General 9 12-13-2003 09:24 PM


All times are GMT -5. The time now is 05:16 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration