diff options
author | Ryan Mitchell <rtmitchell@google.com> | 2018-05-08 11:01:37 -0700 |
---|---|---|
committer | android-build-merger <android-build-merger@google.com> | 2018-05-08 11:01:37 -0700 |
commit | 96930e4faad8ec28e2bbfeffeed8f02109fdcc47 (patch) | |
tree | dfdbc4be1efb28c0b7e5b0cb004f8588d96191b9 | |
parent | dd209c8c1cc379d5617b2fa0e262ca123b7c446c (diff) | |
parent | d94160943d9dbae6946520fe58419c57ec0e6954 (diff) |
Merge "AAPT: Fixed split resource dumping" into pi-dev am: fb07d82086
am: d94160943d
Change-Id: Idfef5422bbe3a3e46ceb1951e6393d2c80852930
-rw-r--r-- | libs/androidfw/ResourceTypes.cpp | 406 |
1 files changed, 211 insertions, 195 deletions
diff --git a/libs/androidfw/ResourceTypes.cpp b/libs/androidfw/ResourceTypes.cpp index b3a3f455bac0..298b699055a5 100644 --- a/libs/androidfw/ResourceTypes.cpp +++ b/libs/androidfw/ResourceTypes.cpp @@ -7367,222 +7367,238 @@ void ResTable::print(bool inclValues) const printf("\n"); } - int packageId = pg->id; - size_t pkgCount = pg->packages.size(); - for (size_t pkgIndex=0; pkgIndex<pkgCount; pkgIndex++) { - const Package* pkg = pg->packages[pkgIndex]; - // Use a package's real ID, since the ID may have been assigned - // if this package is a shared library. - packageId = pkg->package->id; - char16_t tmpName[sizeof(pkg->package->name)/sizeof(pkg->package->name[0])]; - strcpy16_dtoh(tmpName, pkg->package->name, sizeof(pkg->package->name)/sizeof(pkg->package->name[0])); - printf(" Package %d id=0x%02x name=%s\n", (int)pkgIndex, - pkg->package->id, String8(tmpName).string()); - } - - for (size_t typeIndex=0; typeIndex < pg->types.size(); typeIndex++) { - const TypeList& typeList = pg->types[typeIndex]; - if (typeList.isEmpty()) { - continue; - } - const Type* typeConfigs = typeList[0]; - const size_t NTC = typeConfigs->configs.size(); - printf(" type %d configCount=%d entryCount=%d\n", - (int)typeIndex, (int)NTC, (int)typeConfigs->entryCount); - if (typeConfigs->typeSpecFlags != NULL) { - for (size_t entryIndex=0; entryIndex<typeConfigs->entryCount; entryIndex++) { - uint32_t resID = (0xff000000 & ((packageId)<<24)) - | (0x00ff0000 & ((typeIndex+1)<<16)) - | (0x0000ffff & (entryIndex)); - // Since we are creating resID without actually - // iterating over them, we have no idea which is a - // dynamic reference. We must check. - if (packageId == 0) { - pg->dynamicRefTable.lookupResourceId(&resID); - } - - resource_name resName; - if (this->getResourceName(resID, true, &resName)) { - String8 type8; - String8 name8; - if (resName.type8 != NULL) { - type8 = String8(resName.type8, resName.typeLen); - } else { - type8 = String8(resName.type, resName.typeLen); - } - if (resName.name8 != NULL) { - name8 = String8(resName.name8, resName.nameLen); - } else { - name8 = String8(resName.name, resName.nameLen); - } - printf(" spec resource 0x%08x %s:%s/%s: flags=0x%08x\n", - resID, - CHAR16_TO_CSTR(resName.package, resName.packageLen), - type8.string(), name8.string(), - dtohl(typeConfigs->typeSpecFlags[entryIndex])); - } else { - printf(" INVALID TYPE CONFIG FOR RESOURCE 0x%08x\n", resID); - } - } - } - for (size_t configIndex=0; configIndex<NTC; configIndex++) { - const ResTable_type* type = typeConfigs->configs[configIndex]; - if ((((uint64_t)type)&0x3) != 0) { - printf(" NON-INTEGER ResTable_type ADDRESS: %p\n", type); - continue; - } - - // Always copy the config, as fields get added and we need to - // set the defaults. - ResTable_config thisConfig; - thisConfig.copyFromDtoH(type->config); - - String8 configStr = thisConfig.toString(); - printf(" config %s", configStr.size() > 0 - ? configStr.string() : "(default)"); - if (type->flags != 0u) { - printf(" flags=0x%02x", type->flags); - if (type->flags & ResTable_type::FLAG_SPARSE) { - printf(" [sparse]"); - } - } - - printf(":\n"); + // Determine the number of resource splits for the resource types in this package. + // It needs to be done outside of the loop below so all of the information for a + // is displayed in a single block. Otherwise, a resource split's resource types + // would be interleaved with other splits. + size_t splitCount = 0; + for (size_t typeIndex = 0; typeIndex < pg->types.size(); typeIndex++) { + splitCount = max(splitCount, pg->types[typeIndex].size()); + } - size_t entryCount = dtohl(type->entryCount); - uint32_t entriesStart = dtohl(type->entriesStart); - if ((entriesStart&0x3) != 0) { - printf(" NON-INTEGER ResTable_type entriesStart OFFSET: 0x%x\n", entriesStart); - continue; - } - uint32_t typeSize = dtohl(type->header.size); - if ((typeSize&0x3) != 0) { - printf(" NON-INTEGER ResTable_type header.size: 0x%x\n", typeSize); + int packageId = pg->id; + for (size_t splitIndex = 0; splitIndex < splitCount; splitIndex++) { + size_t pkgCount = pg->packages.size(); + for (size_t pkgIndex=0; pkgIndex<pkgCount; pkgIndex++) { + const Package* pkg = pg->packages[pkgIndex]; + // Use a package's real ID, since the ID may have been assigned + // if this package is a shared library. + packageId = pkg->package->id; + char16_t tmpName[sizeof(pkg->package->name)/sizeof(pkg->package->name[0])]; + strcpy16_dtoh(tmpName, pkg->package->name, + sizeof(pkg->package->name)/sizeof(pkg->package->name[0])); + printf(" Package %d id=0x%02x name=%s\n", (int)pkgIndex, + pkg->package->id, String8(tmpName).string()); + } + + for (size_t typeIndex = 0; typeIndex < pg->types.size(); typeIndex++) { + const TypeList& typeList = pg->types[typeIndex]; + if (splitIndex >= typeList.size() || typeList.isEmpty()) { + // Only dump if the split exists and contains entries for this type continue; } - - const uint32_t* const eindex = (const uint32_t*) - (((const uint8_t*)type) + dtohs(type->header.headerSize)); - for (size_t entryIndex=0; entryIndex<entryCount; entryIndex++) { - size_t entryId; - uint32_t thisOffset; - if (type->flags & ResTable_type::FLAG_SPARSE) { - const ResTable_sparseTypeEntry* entry = - reinterpret_cast<const ResTable_sparseTypeEntry*>( - eindex + entryIndex); - entryId = dtohs(entry->idx); - // Offsets are encoded as divided by 4. - thisOffset = static_cast<uint32_t>(dtohs(entry->offset)) * 4u; - } else { - entryId = entryIndex; - thisOffset = dtohl(eindex[entryIndex]); - if (thisOffset == ResTable_type::NO_ENTRY) { - continue; + const Type* typeConfigs = typeList[splitIndex]; + const size_t NTC = typeConfigs->configs.size(); + printf(" type %d configCount=%d entryCount=%d\n", + (int)typeIndex, (int)NTC, (int)typeConfigs->entryCount); + if (typeConfigs->typeSpecFlags != NULL) { + for (size_t entryIndex=0; entryIndex<typeConfigs->entryCount; entryIndex++) { + uint32_t resID = (0xff000000 & ((packageId)<<24)) + | (0x00ff0000 & ((typeIndex+1)<<16)) + | (0x0000ffff & (entryIndex)); + // Since we are creating resID without actually + // iterating over them, we have no idea which is a + // dynamic reference. We must check. + if (packageId == 0) { + pg->dynamicRefTable.lookupResourceId(&resID); } - } - uint32_t resID = (0xff000000 & ((packageId)<<24)) - | (0x00ff0000 & ((typeIndex+1)<<16)) - | (0x0000ffff & (entryId)); - if (packageId == 0) { - pg->dynamicRefTable.lookupResourceId(&resID); - } - resource_name resName; - if (this->getResourceName(resID, true, &resName)) { - String8 type8; - String8 name8; - if (resName.type8 != NULL) { - type8 = String8(resName.type8, resName.typeLen); - } else { - type8 = String8(resName.type, resName.typeLen); - } - if (resName.name8 != NULL) { - name8 = String8(resName.name8, resName.nameLen); + resource_name resName; + if (this->getResourceName(resID, true, &resName)) { + String8 type8; + String8 name8; + if (resName.type8 != NULL) { + type8 = String8(resName.type8, resName.typeLen); + } else { + type8 = String8(resName.type, resName.typeLen); + } + if (resName.name8 != NULL) { + name8 = String8(resName.name8, resName.nameLen); + } else { + name8 = String8(resName.name, resName.nameLen); + } + printf(" spec resource 0x%08x %s:%s/%s: flags=0x%08x\n", + resID, + CHAR16_TO_CSTR(resName.package, resName.packageLen), + type8.string(), name8.string(), + dtohl(typeConfigs->typeSpecFlags[entryIndex])); } else { - name8 = String8(resName.name, resName.nameLen); + printf(" INVALID TYPE CONFIG FOR RESOURCE 0x%08x\n", resID); } - printf(" resource 0x%08x %s:%s/%s: ", resID, - CHAR16_TO_CSTR(resName.package, resName.packageLen), - type8.string(), name8.string()); - } else { - printf(" INVALID RESOURCE 0x%08x: ", resID); - } - if ((thisOffset&0x3) != 0) { - printf("NON-INTEGER OFFSET: 0x%x\n", thisOffset); - continue; } - if ((thisOffset+sizeof(ResTable_entry)) > typeSize) { - printf("OFFSET OUT OF BOUNDS: 0x%x+0x%x (size is 0x%x)\n", - entriesStart, thisOffset, typeSize); + } + for (size_t configIndex=0; configIndex<NTC; configIndex++) { + const ResTable_type* type = typeConfigs->configs[configIndex]; + if ((((uint64_t)type)&0x3) != 0) { + printf(" NON-INTEGER ResTable_type ADDRESS: %p\n", type); continue; } - const ResTable_entry* ent = (const ResTable_entry*) - (((const uint8_t*)type) + entriesStart + thisOffset); - if (((entriesStart + thisOffset)&0x3) != 0) { - printf("NON-INTEGER ResTable_entry OFFSET: 0x%x\n", - (entriesStart + thisOffset)); - continue; + // Always copy the config, as fields get added and we need to + // set the defaults. + ResTable_config thisConfig; + thisConfig.copyFromDtoH(type->config); + + String8 configStr = thisConfig.toString(); + printf(" config %s", configStr.size() > 0 + ? configStr.string() : "(default)"); + if (type->flags != 0u) { + printf(" flags=0x%02x", type->flags); + if (type->flags & ResTable_type::FLAG_SPARSE) { + printf(" [sparse]"); + } } - uintptr_t esize = dtohs(ent->size); - if ((esize&0x3) != 0) { - printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize); + printf(":\n"); + + size_t entryCount = dtohl(type->entryCount); + uint32_t entriesStart = dtohl(type->entriesStart); + if ((entriesStart&0x3) != 0) { + printf(" NON-INTEGER ResTable_type entriesStart OFFSET: 0x%x\n", + entriesStart); continue; } - if ((thisOffset+esize) > typeSize) { - printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+%p (size is 0x%x)\n", - entriesStart, thisOffset, (void *)esize, typeSize); + uint32_t typeSize = dtohl(type->header.size); + if ((typeSize&0x3) != 0) { + printf(" NON-INTEGER ResTable_type header.size: 0x%x\n", typeSize); continue; } - const Res_value* valuePtr = NULL; - const ResTable_map_entry* bagPtr = NULL; - Res_value value; - if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) { - printf("<bag>"); - bagPtr = (const ResTable_map_entry*)ent; - } else { - valuePtr = (const Res_value*) - (((const uint8_t*)ent) + esize); - value.copyFrom_dtoh(*valuePtr); - printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)", - (int)value.dataType, (int)value.data, - (int)value.size, (int)value.res0); - } + const uint32_t* const eindex = (const uint32_t*) + (((const uint8_t*)type) + dtohs(type->header.headerSize)); + for (size_t entryIndex=0; entryIndex<entryCount; entryIndex++) { + size_t entryId; + uint32_t thisOffset; + if (type->flags & ResTable_type::FLAG_SPARSE) { + const ResTable_sparseTypeEntry* entry = + reinterpret_cast<const ResTable_sparseTypeEntry*>( + eindex + entryIndex); + entryId = dtohs(entry->idx); + // Offsets are encoded as divided by 4. + thisOffset = static_cast<uint32_t>(dtohs(entry->offset)) * 4u; + } else { + entryId = entryIndex; + thisOffset = dtohl(eindex[entryIndex]); + if (thisOffset == ResTable_type::NO_ENTRY) { + continue; + } + } - if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) { - printf(" (PUBLIC)"); - } - printf("\n"); - - if (inclValues) { - if (valuePtr != NULL) { - printf(" "); - print_value(typeConfigs->package, value); - } else if (bagPtr != NULL) { - const int N = dtohl(bagPtr->count); - const uint8_t* baseMapPtr = (const uint8_t*)ent; - size_t mapOffset = esize; - const ResTable_map* mapPtr = (ResTable_map*)(baseMapPtr+mapOffset); - const uint32_t parent = dtohl(bagPtr->parent.ident); - uint32_t resolvedParent = parent; - if (Res_GETPACKAGE(resolvedParent) + 1 == 0) { - status_t err = pg->dynamicRefTable.lookupResourceId(&resolvedParent); - if (err != NO_ERROR) { - resolvedParent = 0; - } + uint32_t resID = (0xff000000 & ((packageId)<<24)) + | (0x00ff0000 & ((typeIndex+1)<<16)) + | (0x0000ffff & (entryId)); + if (packageId == 0) { + pg->dynamicRefTable.lookupResourceId(&resID); + } + resource_name resName; + if (this->getResourceName(resID, true, &resName)) { + String8 type8; + String8 name8; + if (resName.type8 != NULL) { + type8 = String8(resName.type8, resName.typeLen); + } else { + type8 = String8(resName.type, resName.typeLen); } - printf(" Parent=0x%08x(Resolved=0x%08x), Count=%d\n", - parent, resolvedParent, N); - for (int i=0; i<N && mapOffset < (typeSize-sizeof(ResTable_map)); i++) { - printf(" #%i (Key=0x%08x): ", - i, dtohl(mapPtr->name.ident)); - value.copyFrom_dtoh(mapPtr->value); + if (resName.name8 != NULL) { + name8 = String8(resName.name8, resName.nameLen); + } else { + name8 = String8(resName.name, resName.nameLen); + } + printf(" resource 0x%08x %s:%s/%s: ", resID, + CHAR16_TO_CSTR(resName.package, resName.packageLen), + type8.string(), name8.string()); + } else { + printf(" INVALID RESOURCE 0x%08x: ", resID); + } + if ((thisOffset&0x3) != 0) { + printf("NON-INTEGER OFFSET: 0x%x\n", thisOffset); + continue; + } + if ((thisOffset+sizeof(ResTable_entry)) > typeSize) { + printf("OFFSET OUT OF BOUNDS: 0x%x+0x%x (size is 0x%x)\n", + entriesStart, thisOffset, typeSize); + continue; + } + + const ResTable_entry* ent = (const ResTable_entry*) + (((const uint8_t*)type) + entriesStart + thisOffset); + if (((entriesStart + thisOffset)&0x3) != 0) { + printf("NON-INTEGER ResTable_entry OFFSET: 0x%x\n", + (entriesStart + thisOffset)); + continue; + } + + uintptr_t esize = dtohs(ent->size); + if ((esize&0x3) != 0) { + printf("NON-INTEGER ResTable_entry SIZE: %p\n", (void *)esize); + continue; + } + if ((thisOffset+esize) > typeSize) { + printf("ResTable_entry OUT OF BOUNDS: 0x%x+0x%x+%p (size is 0x%x)\n", + entriesStart, thisOffset, (void *)esize, typeSize); + continue; + } + + const Res_value* valuePtr = NULL; + const ResTable_map_entry* bagPtr = NULL; + Res_value value; + if ((dtohs(ent->flags)&ResTable_entry::FLAG_COMPLEX) != 0) { + printf("<bag>"); + bagPtr = (const ResTable_map_entry*)ent; + } else { + valuePtr = (const Res_value*) + (((const uint8_t*)ent) + esize); + value.copyFrom_dtoh(*valuePtr); + printf("t=0x%02x d=0x%08x (s=0x%04x r=0x%02x)", + (int)value.dataType, (int)value.data, + (int)value.size, (int)value.res0); + } + + if ((dtohs(ent->flags)&ResTable_entry::FLAG_PUBLIC) != 0) { + printf(" (PUBLIC)"); + } + printf("\n"); + + if (inclValues) { + if (valuePtr != NULL) { + printf(" "); print_value(typeConfigs->package, value); - const size_t size = dtohs(mapPtr->value.size); - mapOffset += size + sizeof(*mapPtr)-sizeof(mapPtr->value); - mapPtr = (ResTable_map*)(baseMapPtr+mapOffset); + } else if (bagPtr != NULL) { + const int N = dtohl(bagPtr->count); + const uint8_t* baseMapPtr = (const uint8_t*)ent; + size_t mapOffset = esize; + const ResTable_map* mapPtr = (ResTable_map*)(baseMapPtr+mapOffset); + const uint32_t parent = dtohl(bagPtr->parent.ident); + uint32_t resolvedParent = parent; + if (Res_GETPACKAGE(resolvedParent) + 1 == 0) { + status_t err = + pg->dynamicRefTable.lookupResourceId(&resolvedParent); + if (err != NO_ERROR) { + resolvedParent = 0; + } + } + printf(" Parent=0x%08x(Resolved=0x%08x), Count=%d\n", + parent, resolvedParent, N); + for (int i=0; + i<N && mapOffset < (typeSize-sizeof(ResTable_map)); i++) { + printf(" #%i (Key=0x%08x): ", + i, dtohl(mapPtr->name.ident)); + value.copyFrom_dtoh(mapPtr->value); + print_value(typeConfigs->package, value); + const size_t size = dtohs(mapPtr->value.size); + mapOffset += size + sizeof(*mapPtr)-sizeof(mapPtr->value); + mapPtr = (ResTable_map*)(baseMapPtr+mapOffset); + } } } } |