简单的进程加载器内存映射 [英] Simple process loader memory mapping

查看:178
本文介绍了简单的进程加载器内存映射的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我为Linux编写了一个非常简单的进程加载器。我加载的可执行文件已经编译,我知道每个人期望在内存中找到的位置。我尝试的第一种方法是使用 mmap()手动将每个代码或数据部分放置在正确的位置,例如

I'm writing a very simple process loader for Linux. The executables I'm loading are already compiled, and I know where each one expects to be found in memory. The first approach I tried was using mmap() to manually place each code or data section at the correct location, like

mmap(addr, size, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0)

除非我删除MAP_FIXED标志,否则它会被segfault,因为看起来一个块的地址与内存中已经存在的内容冲突,甚至可能与加载器本身冲突。地址 0x401000 似乎是有问题的。

which segfaults unless I remove the MAP_FIXED flag because, it seems, the address of one block conflicts with something already in memory, possibly even the loader itself; the address 0x401000 seems to be the problematic one.

我真的不知道从哪里开始一。朋友建议虚拟化内存访问操作;我不知道我会采取什么样的性能打击,我不知道它是如何做,但它可能是一个选择。我真正想做的是创建一个空的进程,就其所涉及的内存的全部运行,所以没有什么将加载到用户空间,直到我想要它。 空过程的整个概念可能是无意义的,但它是描述我想要的最好的方式。

I'm not really even sure where to begin with this one. A friend suggested virtualizing memory access operations; I'm not sure what kind of performance hits I'd take for that, and I have no clue how it's done, but it might be an option. What I'd really love to do is create an "empty" process, which would have, as far as it was concerned, full run of the memory, so nothing would be loaded into the user space until I wanted it to be. The whole concept of an "empty" process might be meaningless, but it's the best way to describe what I want. I'm pretty desperate for some references or examples that might help me.

推荐答案

随着你的进程运行(可能在睡眠中打盹(1000);),看一下它的/ proc / pid / maps。这将告诉你什么0x401000用于。

With your process running (maybe snoozing in "sleep(1000);"), look at its /proc/pid/maps. That will tell you what 0x401000 is used for.

~$ sleep 1h &
[3] 2033
~$ cat /proc/2033/maps
00110000-002af000 r-xp 00000000 08:01 1313056    /lib/i386-linux-gnu/libc-2.15.so
...

在我的盒子上,/ bin / sleep不使用

Here on my box, /bin/sleep doesn't use that block, and neither does my little one-liner program.

你可能在一些想要在那里登陆的图书馆连接?

You're probably linking in some library which wants to land there?

因此,一种方法是早点分配你需要的块(在main()运行之前 - 在其他地方查找该信息)。

So one way would be to allocate the block you need way early (long before main() runs -- look elsewhere for that info).

另一种方法是将你的代码链接到你不知道的地址(可能是你自己生成x86操作码,否则链接 ,所以不应该是一个延伸)。

Another way is to link your code to some address you "know" isn't taken (presumably, you're generating the x86 opcodes yourself, or otherwise "linking", so that shouldn't be a stretch).

另一个更好的选择是让你的代码可重定位。事实上,你不想替换整个进程的地址空间(正是exec的作用)或多或少说你的代码应该是这样的。

Another, better, option is to make your code relocatable. The fact that you don't want to replace the entire process's address space (precisely what exec does) more or less says that your code should be just that.

一个可用的地址,加载那里的位,并根据需要,执行重定位(所以你的磁盘文件格式,如果它不是ELF,将需要包括重定位信息)。这是很高的道路,明显的事情你会接下来从你的装载器。

So find a usable address, load the bits there, and, as needed, perform the relocations (so your on-disk file format, if it's not ELF, will need to include reloc info). That's the high road, and the obvious thing you'll want next from your loader.

当然,这很可能意味着重新实现dlopen()自己。我假设你只是想学习它是如何工作的 - 如果没有,人dlopen。 Stephane的规则Zero:它已经存在了;)

Of course, that pretty much means reimplementing dlopen() yourself. I assume you're just trying to learn how it works -- if not, man dlopen. Stephane's Rule Zero: it's already there ;-)

不要忘记支持从你的代码链接其他库(没有重复),dlclose RTLD_ *模式,荣誉MYCUSTOMLD_LIBRARY_PATH,GCC的__thread说明符等; - )

Don't forget to support linking other libraries from your code (without duplication), dlclose(), initializers, the various RTLD_* modes, honor MYCUSTOMLD_LIBRARY_PATH, GCC's __thread specifier, etc. ;-)

这篇关于简单的进程加载器内存映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆