2011-05-04 28 views
2

我正在编写一个MIPS32仿真器,并希望在使用gcc编译C程序时可以使用整个标准C库(可能与GNU扩展)。libc如何工作?

据我所知,在这一点上,I/O由MIPS32架构上的系统调用处理。如何使用libc/glibc成功运行程序,如何判断需要模拟的系统调用?(没有反复试验)

编辑:请参阅this了解我的意思是系统调用的例子。

(您可以检查出该项目here如果您有兴趣,欢迎任何的反馈。记住,这是在一个非常早期)

+0

我是否理解你的问题意味着你想将系统调用传递给主机的libc? – Blrfl 2011-05-04 13:03:56

+0

不完全。那么,从某种意义上说,最终它是主机的系统调用将被执行,例如,程序将一个字符输出到模拟器的标准输出。但我并不关心如何管理它,只是模拟器可以执行libc使用的系统调用。 – 2011-05-04 13:15:06

+0

换句话说,我会编写C++代码来模拟仿真器中的系统调用。 – 2011-05-04 13:17:12

回答

6

非常简答

阅读更长的答案。

简答

如果您打算提供自定义的libc中的使用您的仿真器的一些功能,将主机OS执行你的系统调用,你必须实现所有的人。

更长的答案

退后一步一分钟,看东西都在真实(非仿真)系统通常分层的方式:

  1. 外设有一些I/O接口(例如,编号的端口或内存映射),CPU可以使其发痒,使他们能够做任何事情。
  2. CPU运行了解如何操作硬件的软件。这可以是一个单一目的程序或运行其他程序的操作系统。由于libc在图中,我们假设有一个操作系统,它是Unix-y的东西。
  3. 由操作系统运行的用户空间程序使用自己和操作系统之间定义的接口来要求执行某些“系统”功能。

你试图完成的任务是在第3层和第2层之间进行,其中libc或用户代码中的函数执行OS定义为触发系统调用的任何操作。这开辟了蠕虫的众多罐:

  • 什么OS定义为触发系统调用从OS到不同的操作系统和同一操作系统的不同版本之间(很少)。通过提供可动态链接的libc,可以在“真实”系统上缓解此问题,从而可以隐藏这些细节。除此之外,如果你想运行一个MIPS32二进制文件,它是否使用你的模拟器支持的系统调用约定?

  • 您需要提供一个自定义libc,它可以让您的模拟器识别出一些特定的系统调用并执行它。您希望运行的任何程序都必须交叉编译为MIPS32并与其静态链接,该程序需要的任何其他库(libm都会想到)。或者,您的模拟器软件包需要提供动态链接器的模拟以及所有必需库的动态链接副本,因为在主机上打开这些副本将不起作用。如果你有足够的资源来重新编译程序,移植可能比模拟更好。

  • 任何对特定系统上的文件路径进行假设的假设代码,或者对某些设备(它们本身就是文件)中的特定假设都无法正确运行。

  • 如果您提供的是第2层,那么您将自行签名以提供对整个操作系统的特定版本的行为的完整,正确的模拟。有些电话如read()write()很容易处理;其他人喜欢fork(),uselib()ioctl()会困难得多。您的程序使用的主机操作系统提供的调用和行为也不一定是一对一映射。所有这些都假定主机是Unix,目标程序也是如此。如果目标是针对其他环境编译的,则所有投注均关闭。

最后一点就是为什么大多数仿真器只提供一个CPU以及一些目标系统的硬件的行为(即,一切都在第1层)。有了这些,您可以运行原始系统的启动ROM,操作系统和用户程序,这些都不会改变。有许多existing MIPS32 emulators这样做,并且可以运行在他们模拟的硬件上运行的操作系统的未改变版本。

HTH和你的项目中最好的运气。

+0

@Downvoter,你能解释为什么你认为这是一个不好的答案? – 2011-05-04 15:54:55

+0

+1对不起,你投下了票......我不是downvoter,但是当有人对此做出很好的回答时,我感到很难受 – Jason 2011-05-04 16:03:33

+0

谢谢你的深入解答。 – 2011-05-05 09:02:14

0

大多数ISO标准C库的可写笔直的C.只有少数部分需要访问较低级别的操作系统功能。

至少,您需要在块或字符级别模拟fopen,freadfwrite的基本I/O。不过,您可以采用Unix方法,并在较低级别的openreadwrite调用之上实施这些方法。

而且您必须管理动态内存分配mallocfree

setjmplongjmp,它需要访问执行堆栈。

还有timesignal.h功能。

+0

感谢您的回答,但这并没有多大帮助。我知道我想要效仿什么。 gcc编译的代码可能会使用系统调用来要求处理器实际执行文件I/O等操作。我想知道这些系统调用代码是什么以及他们期望做什么。例如[SPIM](http://www.doc.ic.ac.uk/lab/secondyear/spim/node8.html)为基本功能提供了一些系统调用。 – 2011-05-04 15:13:53

+0

Mea culpa;从你的问题中不清楚你的模拟需要什么水平。我假设你在图书馆级仿效LIBC。 – 2011-05-04 15:34:15

0

我不知道MIPS是如何工作的,但是在Win32上,OS调用必须通过DLL/EXE导入表显式导入进程。 MIPS系统使用的可执行格式可能有些类似。

+0

比这个低一个或两个等级。它是我决定使用的任何格式(可能会写ELF加载器)。 – 2011-05-04 15:27:45

0

通常的做法是不仅模拟CPU,而且模拟一组标准外设。然后,在模拟器中启动一个包含libc和硬件驱动程序的操作系统。 Libc将调用调用仿真器中虚拟硬件的OSes驱动程序。有关流行示例,请参阅DosBox。

你的问题的另一种解释是你不想写一个完整的模拟器,而是一个二进制兼容层,它允许你在非mips32系统上执行mips32二进制文件。 MacOsX(Intel)也可以执行PowerPC应用程序。

在后一种情况下,您需要模拟操作系统ABI(应用程序二进制接口)或者您可以使用libc的ABI。在这两种情况下,你需要实现仿真器和代理代码运行在主机上运行的存根代码:

  • 存根序列化函数调用的参数
  • ...和仿真器内存使用到主机内存发送它们一些特殊的虚拟指令
  • 代理需要打补丁的参数(字节序,整数长度,地址空间...)
  • ...并执行主机系统
  • 的代理,那么paches和序列化的函数调用传出函数参数
  • ...,并将它们发送回存根
  • ...返回的数据给调用者

大部分电话都无法与普通的存根/代理的工作,但需要一个特定的解决方案。

祝你好运!