C/C++知识点之MachOView源码(LoadCommands.mm)
小标 2019-04-22 来源 : 阅读 1250 评论 0

摘要:本文主要向大家介绍了C/C++知识点之MachOView源码(LoadCommands.mm),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。

本文主要向大家介绍了C/C++知识点之MachOView源码(LoadCommands.mm),通过具体的内容向大家展示,希望对大家学习C/C++知识点有所帮助。


加载命令

这里只要分析一个段和段中的一节就好其它都是同样的解析方式,MachO与 ELF 在段与节的分布(这里说的是内存分布,如何加载另说)上没有什么区别。都是文件头后面就是段。段可能包含很多节。只是它增加了一项加载命令。而 ELF 分俩种视图。
// LoadCommands.h


/*
 *  LoadCommands.h
 *  MachOView
 *
 *  Created by psaghelyi on 20/07/2010.
 *
 */

#import "MachOLayout.h"

//类扩展
@interface MachOLayout (LoadCommands)
//获取加载命令的名称
- (NSString *)getNameForCommand:(uint32_t)cmd;
//创建一个用于窗口显示的加载命令项
-(MVNode *)createLoadCommandNode:(MVNode *)parent
                         caption:(NSString *)caption
                        location:(uint32_t)location
                          length:(uint32_t)length
                         command:(uint32_t)command;

@end


// LoadCommands.mm


/*
 *  LoadCommands.mm
 *  MachOView
 *
 *  Created by psaghelyi on 20/07/2010.
 *
 */

#include
#include
#include
#include

#import "Common.h"
#import "LoadCommands.h"
#import "ReadWrite.h"
#import "DataController.h"

using namespace std;

//============================================================================
@implementation MachOLayout (LoadCommands)

//-----------------------------------------------------------------------------
//获取加载命令名称
- (NSString *)getNameForCommand:(uint32_t)cmd
{
  switch(cmd)
  {
    default:                      return @"???";
    case LC_SEGMENT:              return @"LC_SEGMENT";            
    case LC_SYMTAB:               return @"LC_SYMTAB";              
    case LC_SYMSEG:               return @"LC_SYMSEG";             
    case LC_THREAD:               return @"LC_THREAD";             
    case LC_UNIXTHREAD:           return @"LC_UNIXTHREAD";         
    case LC_LOADFVMLIB:           return @"LC_LOADFVMLIB";         
    case LC_IDFVMLIB:             return @"LC_IDFVMLIB";           
    case LC_IDENT:                return @"LC_IDENT";              
    case LC_FVMFILE:              return @"LC_FVMFILE";            
    case LC_PREPAGE:              return @"LC_PREPAGE";            
    case LC_DYSYMTAB:             return @"LC_DYSYMTAB";           
    case LC_LOAD_DYLIB:           return @"LC_LOAD_DYLIB";         
    case LC_ID_DYLIB:             return @"LC_ID_DYLIB";           
    case LC_LOAD_DYLINKER:        return @"LC_LOAD_DYLINKER";      
    case LC_ID_DYLINKER:          return @"LC_ID_DYLINKER";        
    case LC_PREBOUND_DYLIB:       return @"LC_PREBOUND_DYLIB";     
    case LC_ROUTINES:             return @"LC_ROUTINES";           
    case LC_SUB_FRAMEWORK:        return @"LC_SUB_FRAMEWORK";      
    case LC_SUB_UMBRELLA:         return @"LC_SUB_UMBRELLA";       
    case LC_SUB_CLIENT:           return @"LC_SUB_CLIENT";         
    case LC_SUB_LIBRARY:          return @"LC_SUB_LIBRARY";        
    case LC_TWOLEVEL_HINTS:       return @"LC_TWOLEVEL_HINTS";     
    case LC_PREBIND_CKSUM:        return @"LC_PREBIND_CKSUM";      
    case LC_LOAD_WEAK_DYLIB:      return @"LC_LOAD_WEAK_DYLIB";    
    case LC_SEGMENT_64:           return @"LC_SEGMENT_64";         
    case LC_ROUTINES_64:          return @"LC_ROUTINES_64";        
    case LC_UUID:                 return @"LC_UUID";               
    case LC_RPATH:                return @"LC_RPATH";              
    case LC_CODE_SIGNATURE:       return @"LC_CODE_SIGNATURE";     
    case LC_SEGMENT_SPLIT_INFO:   return @"LC_SEGMENT_SPLIT_INFO"; 
    case LC_REEXPORT_DYLIB:       return @"LC_REEXPORT_DYLIB";     
    case LC_LAZY_LOAD_DYLIB:      return @"LC_LAZY_LOAD_DYLIB";    
    case LC_ENCRYPTION_INFO:      return @"LC_ENCRYPTION_INFO";    
    case LC_ENCRYPTION_INFO_64:   return @"LC_ENCRYPTION_INFO_64";
    case LC_DYLD_INFO:            return @"LC_DYLD_INFO";          
    case LC_DYLD_INFO_ONLY:       return @"LC_DYLD_INFO_ONLY";     
    case LC_LOAD_UPWARD_DYLIB:    return @"LC_LOAD_UPWARD_DYLIB";
    case LC_VERSION_MIN_MACOSX:   return @"LC_VERSION_MIN_MACOSX";
    case LC_VERSION_MIN_IPHONEOS: return @"LC_VERSION_MIN_IPHONEOS";
    case LC_FUNCTION_STARTS:      return @"LC_FUNCTION_STARTS";
    case LC_DYLD_ENVIRONMENT:     return @"LC_DYLD_ENVIRONMENT";
    case LC_MAIN:                 return @"LC_MAIN";
    case LC_DATA_IN_CODE:         return @"LC_DATA_IN_CODE";
    case LC_SOURCE_VERSION:       return @"LC_SOURCE_VERSION";
    case LC_DYLIB_CODE_SIGN_DRS:  return @"LC_DYLIB_CODE_SIGN_DRS";
    case LC_LINKER_OPTION:        return @"LC_LINKER_OPTION";
    case LC_LINKER_OPTIMIZATION_HINT: return @"LC_LINKER_OPTIMIZATION_HINT";
  }
}

//-----------------------------------------------------------------------------
//struct segment_command_64 { /* for 64-bit architectures */
//    uint32_t    cmd;             命令加载类型
//    uint32_t    cmdsize;         命令加载的大小
//    char        segname[16];     16 字节的段名
//    uint64_t    vmaddr;          段的虚拟内存地址 VA
//    uint64_t    vmsize;          段的在虚拟内存有大小
//    uint64_t    fileoff;         段在文件中的偏移
//    uint64_t    filesize;        段在文件中的大小
//    vm_prot_t    maxprot;        段页要所需要的最高内存保护(4=r,2=w,1=x)
//    vm_prot_t    initprot;       段页面初始化的内存保护
//    uint32_t    nsects;          段中包含 section 的数量
//    uint32_t    flags;           其它杂项标志位
//};
//加载命令的显示方式
- (MVNode *)createLCSegmentNode:(MVNode *)parent
                     caption:(NSString *)caption
                     //数据的地址
                     location:(uint32_t)location
                     segment_command:(struct segment_command const *)segment_command
{
    //DataController.h中的一个结构
//    struct MVNodeSaver
//    {
//        MVNodeSaver();
//        ~MVNodeSaver();
//
//        void setNode(MVNode * node) { m_node = node; }
//
//    private:
//        MVNodeSaver(MVNodeSaver const &);
//        MVNodeSaver & operator=(MVNodeSaver const &);
//
//        MVNode * __weak m_node;
//    };
  MVNodeSaver nodeSaver;
    //DataController.h中的一个类
    //初始化一个MVNode
  MVNode * node = [parent insertChildWithDetails:caption location:location length:segment_command->cmdsize saver:nodeSaver];
  //创建一个NSRange
  NSRange range = NSMakeRange(location,0);
  NSString * lastReadHex;
  //获取 hex 位置为range.location
    ////获取十六进制 lastReadHex缓冲区
//- (uint32_t)read_uint32:(NSRange &)range lastReadHex:(NSString **)lastReadHex
//{
//    //缓冲区
//  uint32_t buffer;
//    //创建一个range
//  range = NSMakeRange(NSMaxRange(range),sizeof(uint32_t));
//    //可修改的NSMutableData * fileData;
//    //获取指定范围的数据
//  [fileData getBytes:&buffer range:range];
//    //判断lastReadHex是否可以用
//  if (lastReadHex)
//      //转十六进制
//      *lastReadHex = [NSString stringWithFormat:@"%.8X",buffer];
//  //可修改的NSMutableData * realData;
//    //重新读
//  [realData getBytes:&buffer range:range];
//    //返回数据
//  return buffer;
//}

  [dataController read_uint32:range lastReadHex:&lastReadHex];
    // MVTable * details
    //offsetStr = col0;
    //dataStr = col1;
    //descriptionStr = col2;
    //valueStr = col3;
    //右边表格追加一行
  [node.details appendRow:
      //地址(文件偏移地址或者vm内存地址)
     [NSString stringWithFormat:@"%.8lX", range.location]
      //Date数据
     :lastReadHex
      //描述
     :@"Command"
      //加载命令的值(名称)
     :[self getNameForCommand:segment_command->cmd]];
   //设置加载命令的结构体(那个俩字段的结构体)颜色为greenColor
  //MVCellColorAttributeName = @"MVCellColorAttribute";
  [node.details setAttributes:MVCellColorAttributeName,[NSColor greenColor],nil];
  //重新获取 hex
  [dataController read_uint32:range lastReadHex:&lastReadHex];
   //显示Command Size字段
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Command Size"
                         :[NSString stringWithFormat:@"%u", segment_command->cmdsize]];
  //显示颜色
  [node.details setAttributes:MVCellColorAttributeName,[NSColor greenColor],
                              MVUnderlineAttributeName,@"YES",nil];
  //重新取 hex
  [dataController read_string:range fixlen:16 lastReadHex:&lastReadHex];
  //显示字段Segment Name
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Segment Name"
                         :[NSString stringWithFormat:@"%s", string(segment_command->segname,16).c_str()]];
  //VM Address
  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"VM Address"
                         :[NSString stringWithFormat:@"0x%X", segment_command->vmaddr]];
  //VM Size
  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"VM Size"
                         :[NSString stringWithFormat:@"%u", segment_command->vmsize]];
  //File Offset
  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"File Offset"
                         :[NSString stringWithFormat:@"%u", segment_command->fileoff]];
  //File Size
  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"File Size"
                         :[NSString stringWithFormat:@"%u", segment_command->filesize]];
  //Maximum VM Protection
  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Maximum VM Protection"
                         :@""];
  //段页面不能超过的最高内存保护 注意这里是八进制
    //无最高保护
  if (segment_command->maxprot == VM_PROT_NONE)    [node.details appendRow:@"":@"":@"00000000":@"VM_PROT_NONE"];
    //可执行
  if (segment_command->maxprot & VM_PROT_READ)     [node.details appendRow:@"":@"":@"00000001":@"VM_PROT_READ"];
    //可写
  if (segment_command->maxprot & VM_PROT_WRITE)    [node.details appendRow:@"":@"":@"00000002":@"VM_PROT_WRITE"];
    //可读
  if (segment_command->maxprot & VM_PROT_EXECUTE)  [node.details appendRow:@"":@"":@"00000004":@"VM_PROT_EXECUTE"];
  //重新读
  [dataController read_uint32:range lastReadHex:&lastReadHex];
    //段内最初始的内存保护
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Initial VM Protection"
                         :@""];
  //0 1 2 4
  if (segment_command->initprot == VM_PROT_NONE)   [node.details appendRow:@"":@"":@"00000000":@"VM_PROT_NONE"];
  if (segment_command->initprot & VM_PROT_READ)    [node.details appendRow:@"":@"":@"00000001":@"VM_PROT_READ"];
  if (segment_command->initprot & VM_PROT_WRITE)   [node.details appendRow:@"":@"":@"00000002":@"VM_PROT_WRITE"];
  if (segment_command->initprot & VM_PROT_EXECUTE) [node.details appendRow:@"":@"":@"00000004":@"VM_PROT_EXECUTE"];
  //段中节的数量
  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Number of Sections"
                         :[NSString stringWithFormat:@"%u", segment_command->nsects]];
  //其它标志
  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Flags"
                         :@""];
  //该段的文件内容是VM空间的高部分,低部分为零填充(在核心文件用于堆栈)
  if (segment_command->flags & SG_HIGHVM)              [node.details appendRow:@"":@"":@"00000001":@"SG_HIGHVM"];
    //此段是由固定的VM library分配的VM,用于链接编辑器中的重叠检查
  if (segment_command->flags & SG_FVMLIB)              [node.details appendRow:@"":@"":@"00000002":@"SG_FVMLIB"];
    //无重定位
  if (segment_command->flags & SG_NORELOC)             [node.details appendRow:@"":@"":@"00000004":@"SG_NORELOC"];
    //这个部分是受保护的,如果段在文件偏移0处开始,则段的第一页不受保护,该段的所有其他页都受到保护。
  if (segment_command->flags & SG_PROTECTED_VERSION_1) [node.details appendRow:@"":@"":@"00000008":@"SG_PROTECTED_VERSION_1"];
  //返回加载命令 显示结点
  return node;
}
//struct section_64 { /* for 64-bit architectures */
//    char        sectname[16];   节名
//    char        segname[16];    节的所属段名
//    uint64_t    addr;           节的内存中的起始地址
//    uint64_t    size;           节的大小
//    uint32_t    offset;         节的文件偏移
//    uint32_t    align;          节的对齐粒度
//    uint32_t    reloff;         重定位入口的文件偏移
//    uint32_t    nreloc;         需要重定位的入口数量
//    uint32_t    flags;          其它标志 包含包含节的type和attributes
//    uint32_t    reserved1;      记录了它们在dysymtab_command结构中indirectsymoff字段所对应的起始项
//对于 symbol pointer sections 和 stubs sections 来说,reserved1 表示 indirect table 数组的 index。用来索引 section's entries
//    uint32_t    reserved2;      记录了条目的大小或者个数
//    uint32_t    reserved3;    /* reserved */
//};
//-----------------------------------------------------------------------------
//节
- (MVNode *)createSectionNode:(MVNode *)parent
                    caption:(NSString *)caption
                   location:(uint32_t)location
                    section:(struct section const *)section
{
  MVNodeSaver nodeSaver;
  MVNode * node = [parent insertChildWithDetails:caption location:location length:sizeof(struct section) saver:nodeSaver];

  NSRange range = NSMakeRange(location,0);
  NSString * lastReadHex;

  [dataController read_string:range fixlen:16 lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Section Name"
                         :[NSString stringWithFormat:@"%s", string(section->sectname,16).c_str()]];

  [dataController read_string:range fixlen:16 lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Segment Name"
                         :[NSString stringWithFormat:@"%s", string(section->segname,16).c_str()]];

  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Address"
                         :[NSString stringWithFormat:@"0x%X", section->addr]];

  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Size"
                         :[NSString stringWithFormat:@"%u", section->size]];

  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Offset"
                         :[NSString stringWithFormat:@"%u", section->offset]];

  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Alignment"
                         :[NSString stringWithFormat:@"%u", (1 << section->align)]];

  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range.location]
                         :lastReadHex
                         :@"Relocations Offset"
                         :[NSString stringWithFormat:@"%u", section->reloff]];

  [dataController read_uint32:range lastReadHex:&lastReadHex];
  [node.details appendRow:[NSString stringWithFormat:@"%.8lX", range    

本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标编程语言C/C+频道!


本文由 @小标 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程