我写了一个简单的仪器工具(使用Intel Pin API) 跟踪对mmap系统调用的每次调用。 然后我将pintool应用于“date”命令并获得以下输出。 请问几个问题:
1)为什么像“date”这样的简单命令会映射~15 MB?
2)每次调用mmap时,进程的页表都会更新为 包括新创建的映射 - 我是否正确?
3)使用文件描述符-1,内核将0初始化页面。 文件描述符4用于什么?
thread begin 0
entry: addr 0 , length 8 KB , fd -1
exit: returned with 0x2b5d7bc08000
entry: addr 0 , length 101 KB , fd 4
exit: returned with 0x2b5d7bc66000
entry: addr 0 , length 2079 KB , fd 4
exit: returned with 0x2b5d7bcb2000
entry: addr 0x2b5d7beb8000 , length 8 KB , fd 4
exit: returned with 0x2b5d7beb8000
entry: addr 0 , length 3833 KB , fd 4
exit: returned with 0x2b5d7bed0000
entry: addr 0x2b5d7c284000 , length 24 KB , fd 4
exit: returned with 0x2b5d7c284000
entry: addr 0x2b5d7c28a000 , length 17 KB , fd -1
exit: returned with 0x2b5d7c28a000
entry: addr 0 , length 4 KB , fd -1
exit: returned with 0x2b5d7c2b0000
entry: addr 0 , length 2161 KB , fd 4
exit: returned with 0x2b5d7c2ba000
entry: addr 0x2b5d7c4d1000 , length 8 KB , fd 4
exit: returned with 0x2b5d7c4d1000
entry: addr 0x2b5d7c4d3000 , length 13 KB , fd -1
exit: returned with 0x2b5d7c4d3000
entry: addr 0 , length 4 KB , fd -1
exit: returned with 0x2b5d7c4e7000
entry: addr 0 , length 4 KB , fd -1
exit: returned with 0x2b5d7c4ee000
entry: addr 0 , length 4 KB , fd -1
exit: returned with 0x2b5d7c4f3000
entry: addr 0 , length 7051 KB , fd 4
exit: returned with 0x2b5d7c777000
entry: addr 0 , length 4 KB , fd -1
exit: returned with 0x2b5d7c5ff000
entry: addr 0 , length 4 KB , fd -1
exit: returned with 0x2b5d7c665000
thread end 0 code 0
total mapped 15328 KB
如果有人有兴趣,pintool代码是:
#include <iostream>
#include <fstream>
#include <string>
#include <cassert>
#include <syscall.h>
#include "pin.H"
KNOB<string> KnobOutputFile(KNOB_MODE_WRITEONCE, "pintool",
"o", "PintoolResults.out", "specify output file name");
// Thread specific data
TLS_KEY mlog_key;
void PrintIndent(std::ostream& os, int indent) {
for (int i=0 ; i<indent ; ++i)
os << " ";
}
// MLOG - thread specific data that is not handled by the buffering API.
class MLOG {
public:
MLOG(THREADID tid)
: indent(3), syscall_num(0), total_mapped(0) {
std::string output_file_name = KnobOutputFile.Value() + "-" + decstr(tid);
out.open(output_file_name.c_str());
if (!out) {
std::cerr << "Error: could not open output file." << std::endl;
}
}
~MLOG() {
out.close();
}
/* Public class members */
std::ofstream out; // where to write the results
int indent;
// 3 integers to save the context before syscalls
UINT64 syscall_num;
UINT64 total_mapped;
};
//==============================================================
// Analysis Routines
//==============================================================
// This routine is executed every time a thread is created.
VOID ThreadStart(THREADID tid, CONTEXT *ctxt, INT32 flags, VOID *v) {
// There is a new MLOG for every thread
MLOG * mlog = new MLOG(tid);
// A thread will need to look up its MLOG, so save pointer in TLS
PIN_SetThreadData(mlog_key, mlog, tid);
mlog->out << "thread begin " << tid << std::endl;
}
// This routine is executed every time a thread is destroyed.
VOID ThreadFini(THREADID tid, const CONTEXT *ctxt, INT32 code, VOID *v) {
MLOG * mlog = static_cast<MLOG*>(PIN_GetThreadData(mlog_key, tid));
mlog->out << "thread end " << tid << " code " << code << std::endl;
mlog->out << "total mapped " << std::dec << (mlog->total_mapped>>10ul) << " KB" << std::endl;
delete mlog;
PIN_SetThreadData(mlog_key, 0, tid);
}
VOID SyscallEntry(THREADID tid, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v) {
MLOG * mlog = static_cast<MLOG*>(PIN_GetThreadData(mlog_key, tid));
mlog->syscall_num = PIN_GetSyscallNumber(ctxt, std);
UINT64 syscall_arg0 = PIN_GetSyscallArgument(ctxt, std, 0);
UINT64 syscall_arg1 = PIN_GetSyscallArgument(ctxt, std, 1);
UINT64 syscall_arg4 = PIN_GetSyscallArgument(ctxt, std, 4);
if (mlog->syscall_num == SYS_mmap) {
PrintIndent(mlog->out, mlog->indent);
mlog->out << "entry: addr " << std::hex << std::showbase << syscall_arg0
<< " , length " << std::dec << (syscall_arg1 >> 10ul) << " KB"
<< " , fd " << std::dec << static_cast<int>(syscall_arg4) << "\n";
mlog->indent += 1;
mlog->total_mapped += syscall_arg1;
}
}
VOID SyscallExit(THREADID tid, CONTEXT *ctxt, SYSCALL_STANDARD std, VOID *v) {
MLOG* mlog = static_cast<MLOG*>(PIN_GetThreadData(mlog_key, tid));
UINT64 syscall_num = mlog->syscall_num;
if (syscall_num == SYS_mmap) {
mlog->indent -= 1;
assert(mlog->indent >= 0);
PrintIndent(mlog->out, mlog->indent);
mlog->out << "exit: returned with " << std::hex << std::showbase
<< PIN_GetSyscallReturn(ctxt, std) << "\n";
}
}
/* ===================================================================== */
/* Print Help Message */
/* ===================================================================== */
INT32 Usage() {
PIN_ERROR("This Pintool prints a trace of malloc calls in the guest application\n"
+ KNOB_BASE::StringKnobSummary() + "\n");
return -1;
}
/* ===================================================================== */
/* Main */
/* ===================================================================== */
int main(INT32 argc, CHAR **argv) {
// Initialize pin
if (PIN_Init(argc, argv)) return Usage();
PIN_InitSymbols();
// Register Analysis routines to be called when a thread begins/ends
PIN_AddThreadStartFunction(ThreadStart, 0);
PIN_AddThreadFiniFunction(ThreadFini, 0);
PIN_AddSyscallEntryFunction(SyscallEntry, 0);
PIN_AddSyscallExitFunction(SyscallExit, 0);
// Never returns
PIN_StartProgram();
return 0;
}