Example #1
0
File: info.py Project: zcutlip/LLDB
def tryHeapAddress(addr, target, options):
    returnDescription = ""
    cleanCommand = 'void * ptr = (void *){};'.format(addr.GetLoadAddress(target))
    cleanCommand += 'BOOL verboseMode = {};'.format("YES" if options.verbose else "NO")
    cleanCommand += r'''


    @import Foundation;

    NSMutableString *retString;
    if ((void*)malloc_zone_from_ptr(ptr)) {

      retString = (NSMutableString*)[[NSMutableString alloc] initWithFormat:@"%p heap pointer, (0x%x bytes), zone: %p", ptr, (size_t)malloc_good_size((size_t)malloc_size(ptr)), (void*)malloc_zone_from_ptr(ptr)];
    }
    
    retString ? retString : nil;
    '''

    val = target.EvaluateExpression(cleanCommand, ds.genExpressionOptions())
    
    if val.GetError().success == False or val.GetValueAsUnsigned() == 0 or val.description is None:
        return False, ""
    
    returnDescription += val.description
    return True, returnDescription
Example #2
0
def processStackTraceStringFromAddresses(frameAddresses, target, options=None):
    frame_string = ''
    startAddresses = [
        target.ResolveLoadAddress(f).symbol.addr.GetLoadAddress(target)
        for f in frameAddresses
    ]
    script = generateExecutableMethodsScript(startAddresses)

    # New content start 1
    methods = target.EvaluateExpression(script, ds.genExpressionOptions())
    charPointerType = target.FindFirstType(
        "char").GetPointerType().GetArrayType(len(frameAddresses))
    methods = methods.Cast(charPointerType)
    methodsVal = lldb.value(methods)
    # New content end 1

    # Enumerate each of the SBFrames in address list
    pointerType = target.FindFirstType("char").GetPointerType()
    for index, frameAddr in enumerate(frameAddresses):
        addr = target.ResolveLoadAddress(frameAddr)
        symbol = addr.symbol

        # New content start 2
        if symbol.synthetic:  # 1
            children = methodsVal.sbvalue.GetNumChildren()  # 4
            name = ds.attrStr(symbol.name + r' ... unresolved womp womp',
                              'redd')  # 2

            loadAddr = symbol.addr.GetLoadAddress(target)  # 3
            k = str(methodsVal[index]).split('"')  # 5
            if len(k) >= 2:
                name = ds.attrStr(k[1], 'bold')  # 6
        else:
            name = ds.attrStr(str(symbol.name), 'yellow')  # 7
        # New content end 2

        offset_str = ''
        offset = addr.GetLoadAddress(target) - addr.symbol.addr.GetLoadAddress(
            target)
        if offset > 0:
            offset_str = '+ {}'.format(offset)

        i = ds.attrStr('frame #{:<2}:'.format(index), 'grey')
        if options and options.address:
            frame_string += '{} {}`{} {}\n'.format(
                ds.attrStr(hex(addr.GetLoadAddress(target)), 'grey'),
                ds.attrStr(str(addr.module.file.basename), 'cyan'),
                ds.attrStr(str(name), 'yellow'),
                ds.attrStr(offset_str, 'grey'))
        else:
            frame_string += '{} {} {}`{} {}\n'.format(
                i, ds.attrStr(str(hex(addr.GetLoadAddress(target))), 'grey'),
                ds.attrStr(str(addr.module.file.basename), 'cyan'), name,
                ds.attrStr(str(offset_str), 'grey'))

    return frame_string
Example #3
0
def tryHeapAddress(addr, target, options):
    returnDescription = ""
    cleanCommand = 'const void * ptr = (const void *){};'.format(
        addr.GetLoadAddress(target))
    cleanCommand += 'BOOL verboseMode = {};'.format(
        "YES" if options.verbose else "NO")
    cleanCommand += r'''

#ifndef _MALLOC_MALLOC_H_

typedef struct _malloc_zone_t {
    void  *reserved1; 
    void  *reserved2; 
    size_t  (*size)(struct _malloc_zone_t *zone, const void *ptr); 
    void  *(*malloc)(struct _malloc_zone_t *zone, size_t size);
    void  *(*calloc)(struct _malloc_zone_t *zone, size_t num_items, size_t size); 
    void  *(*valloc)(struct _malloc_zone_t *zone, size_t size); 
    void  (*free)(struct _malloc_zone_t *zone, void *ptr);
    void  *(*realloc)(struct _malloc_zone_t *zone, void *ptr, size_t size);
    void  (*destroy)(struct _malloc_zone_t *zone); 
    const char  *zone_name;
    unsigned  (*batch_malloc)(struct _malloc_zone_t *zone, size_t size, void **results, unsigned num_requested); 
    void  (*batch_free)(struct _malloc_zone_t *zone, void **to_be_freed, unsigned num_to_be_freed); 
    struct malloc_introspection_t *introspect;
    unsigned  version;
    void *(*memalign)(struct _malloc_zone_t *zone, size_t alignment, size_t size);
    void (*free_definite_size)(struct _malloc_zone_t *zone, void *ptr, size_t size);
    size_t  (*pressure_relief)(struct _malloc_zone_t *zone, size_t goal);
} malloc_zone_t;

    extern malloc_zone_t* malloc_zone_from_ptr (   const void *  ptr  );
    extern size_t malloc_size  (   const void *  ptr  );
    extern size_t malloc_good_size(size_t size);

    extern const char* malloc_get_zone_name  (   malloc_zone_t *   zone   ) ;
#endif // _MALLOC_MALLOC_H_
    
    

    NSMutableString *retString;
    if (malloc_zone_from_ptr(ptr)) {

        retString = (NSString*)[[NSMutableString alloc] initWithFormat:@"heap pointer found in %s, (%d bytes)", malloc_get_zone_name(malloc_zone_from_ptr(ptr)), malloc_good_size(malloc_size(ptr))];

//*****************************************************************************/
#pragma mark - Ivars
//*****************************************************************************/
  
#define FAST_DATA_MASK          0x00007ffffffffff8UL

typedef struct ivar_t {
#if __x86_64__
    // *offset was originally 64-bit on some x86_64 platforms.
    // We read and write only 32 bits of it.
    // Some metadata provides all 64 bits. This is harmless for unsigned
    // little-endian values.
    // Some code uses all 64 bits. class_addIvar() over-allocates the
    // offset for their benefit.
#endif
    int32_t *offset;
    const char *name;
    const char *type;
    // alignment is sometimes -1; use alignment() instead
    uint32_t alignment_raw;
    uint32_t size;
    
  } ivar_t;
  
  
typedef struct ivar_list_t {
    uint32_t entsizeAndFlags;
    uint32_t count;
    ivar_t *first;
} ivar_list_t;

typedef struct class_ro_t {
    uint32_t flags;
    uint32_t instanceStart;
    uint32_t instanceSize;
#ifdef __LP64__
    uint32_t reserved;
#endif
    
    const uint8_t * ivarLayout;
    
    const char * name;
    /* method_list_t   */ void * baseMethodList;
    /* protocol_list_t */ void * baseProtocols;
    ivar_list_t * ivars;
    uint8_t * weakIvarLayout;
    /* property_list_t */ void *baseProperties;
  
} class_ro_t;
  
  
typedef struct class_rw_t {
    uint32_t flags;
    uint32_t version;
    
    const class_ro_t *ro;
    
    /* method_array_t */ void* methods;        // redefined from method_array_t
    /* property_array_t */ void* properties;   // redefined from property_array_t
    /* protocol_list_t */ void* protocols;    // redefined from protocol_array_t
  
    struct dsobjc_class*   firstSubclass;
    struct dsobjc_class* nextSiblingClass;
    
    char *demangledName;
    
} class_rw_t;
  
  typedef struct dsobjc_class {
    struct dsobjc_class* isa;
    struct dsobjc_class* superclass;
    void *_buckets;             // formerly cache pointer and vtable
    uint32_t _mask;
    uint32_t _occupied;
    uintptr_t bits;
    
    class_rw_t *ds_data() {
      return (class_rw_t *)(bits & FAST_DATA_MASK);
    }
    
  } dsobjc_class;

      dsobjc_class *dsclass = (dsobjc_class*)object_getClass((id)ptr);
      if (dsclass) {
          (void)[retString appendString:(NSString*)[[NSString alloc] initWithFormat:@"\nin %@:\n", (id)NSStringFromClass((id)object_getClass((id)ptr))]];
          ivar_list_t *bivar = dsclass->ds_data()->ro->ivars;  
          if (bivar) {
            for (int i = 0; i < bivar->count; i++) {
                ivar_t *dsiv = (ivar_t *)(&bivar->first);

                int sz = dsiv[i].size;
                int32_t offset = *(int32_t *)dsiv[i].offset;
                char *baseAddr = (char *)ptr;
                char *dstype = (char *)dsiv[i].type;
                char *dsname = (char *)dsiv[i].name;

                // no clue what would be this size
                if (sz == 1) {
                  [retString appendString:(NSString*)[[NSString alloc] initWithFormat:@" %s %-30s\n\t%s\n", dstype, dsname, *((uint8_t *)(char *)ptr + (offset))]];
                  
                // no clue what would be this size
                } else if (sz == 2) {
                  [retString appendString:(NSString*)[[NSString alloc] initWithFormat:@" %s %-30s %p\n", dstype, dsname, *((uint16_t *)(char *)ptr + (offset))]];

                } else if (sz == 4) {
                      uint32_t* offsetAddr32 = *(uint32_t**)(baseAddr + offset);
                      if ((int)strcmp(dstype, "b1")==0 || (int)strcmp(dstype, "b2") ==0 ) {
                           // Its a bool
                          [retString appendString:(NSString*)[[NSString alloc] initWithFormat:@"+0x%-5x%s (%s): %s\n", offset, dsname, dstype,   *(BOOL*)(baseAddr + offset) ? "YES" : "NO"]];
                      } else {
                          [retString appendString:(NSString*)[[NSString alloc] initWithFormat:@"+0x%-5x%s (%s): 0x%012lx\n", offset, dsname, dstype,  offsetAddr32]];
                      }
                } else if (sz == 8) {
                    uint64_t* offsetAddr64 = *(uint64_t**)(baseAddr + offset);
                    NSMutableString *tmpType = nil;
                    if (dstype[0] == '@' && strlen(dstype) > 1) {
                        tmpType = (NSString*)[(NSString*)[(NSString*)[(NSString*)[NSString stringWithUTF8String:dstype] stringByReplacingOccurrencesOfString:@"@" withString:@""] stringByReplacingOccurrencesOfString:@"\"" withString:@""] stringByAppendingString:@"*"];
                    } else if (dstype[0] == '@') {
                        tmpType = @"id";
                    } else {
                        tmpType = (NSString*)[NSString stringWithUTF8String:dstype];
                    }

                    if (offsetAddr64) {

                       if ((char*)object_getClassName((id)offsetAddr64)) {
                           if (verboseMode) {
                             [retString appendString:(NSString*)[[NSString alloc] initWithFormat:@"+0x%-5x%s (%@): [0x%012lx] %@\n", offset, dsname, tmpType, offsetAddr64, (NSString*)[(id _Nullable)offsetAddr64 debugDescription] ]];
                           } else {
                             [retString appendString:(NSString*)[[NSString alloc] initWithFormat:@"+0x%-5x%s (%@): %@\n", offset, dsname, tmpType,  (NSString*)[(id _Nullable)offsetAddr64 debugDescription] ]];
                           }
                       } else {
                           [retString appendString:(NSString*)[[NSString alloc] initWithFormat:@"+0x%-5x%s (%@): 0x%012lx\n", offset, dsname, tmpType,  offsetAddr64]];
                       }
                    } else {
                       [retString appendString:(NSString*)[[NSString alloc] initWithFormat:@"+0x%-5x%s (%@): nil\n", offset, dsname, tmpType]];
                    }
                }

            }
        }
      }


    } else {
          retString = nil;
    }
    
// 0x00007ffffffffff8UL
    retString
    '''

    # lldb.debugger.HandleCommand("exp -l objc -- " + cleanCommand)
    # return False, returnDescription
    val = target.EvaluateExpression(cleanCommand, ds.genExpressionOptions())
    if val.GetValueAsUnsigned() == 0:
        return False, ""

    returnDescription += '{}'.format(val.description)

    return True, returnDescription