mirror of
https://github.com/SciresM/hactool
synced 2024-11-22 20:13:08 +00:00
Fix Intersection bucket retrievals
This commit is contained in:
parent
3d12b43f7b
commit
67d09c125b
3 changed files with 42 additions and 10 deletions
25
bktr.c
25
bktr.c
|
@ -1,6 +1,10 @@
|
||||||
#include "bktr.h"
|
#include "bktr.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
bktr_relocation_bucket_t *bktr_get_relocation_bucket(bktr_relocation_block_t *block, uint32_t i) {
|
||||||
|
return (bktr_relocation_bucket_t *)((uint8_t *)block->buckets + (sizeof(bktr_relocation_bucket_t) + sizeof(bktr_relocation_entry_t)) * i);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a relocation entry from offset and relocation block. */
|
/* Get a relocation entry from offset and relocation block. */
|
||||||
bktr_relocation_entry_t *bktr_get_relocation(bktr_relocation_block_t *block, uint64_t offset) {
|
bktr_relocation_entry_t *bktr_get_relocation(bktr_relocation_block_t *block, uint64_t offset) {
|
||||||
/* Weak check for invalid offset. */
|
/* Weak check for invalid offset. */
|
||||||
|
@ -9,16 +13,19 @@ bktr_relocation_entry_t *bktr_get_relocation(bktr_relocation_block_t *block, uin
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
bktr_relocation_bucket_t *bucket = &block->buckets[0];
|
uint32_t bucket_num = 0;
|
||||||
for (unsigned int i = 1; i < block->num_buckets; i++) {
|
for (unsigned int i = 1; i < block->num_buckets; i++) {
|
||||||
if (block->bucket_virtual_offsets[i] < offset) {
|
if (block->bucket_virtual_offsets[i] <= offset) {
|
||||||
bucket++;
|
bucket_num++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bktr_relocation_bucket_t *bucket = bktr_get_relocation_bucket(block, bucket_num);
|
||||||
|
|
||||||
if (bucket->num_entries == 1) { /* Check for edge case, short circuit. */
|
if (bucket->num_entries == 1) { /* Check for edge case, short circuit. */
|
||||||
return &bucket->entries[0];
|
return &bucket->entries[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Binary search. */
|
/* Binary search. */
|
||||||
uint32_t low = 0, high = bucket->num_entries - 1;
|
uint32_t low = 0, high = bucket->num_entries - 1;
|
||||||
while (low <= high) {
|
while (low <= high) {
|
||||||
|
@ -37,6 +44,10 @@ bktr_relocation_entry_t *bktr_get_relocation(bktr_relocation_block_t *block, uin
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bktr_subsection_bucket_t *bktr_get_subsection_bucket(bktr_subsection_block_t *block, uint32_t i) {
|
||||||
|
return (bktr_subsection_bucket_t *)((uint8_t *)block->buckets + (sizeof(bktr_subsection_bucket_t) + sizeof(bktr_subsection_entry_t)) * i);
|
||||||
|
}
|
||||||
|
|
||||||
/* Get a subsection entry from offset and subsection block .*/
|
/* Get a subsection entry from offset and subsection block .*/
|
||||||
bktr_subsection_entry_t *bktr_get_subsection(bktr_subsection_block_t *block, uint64_t offset) {
|
bktr_subsection_entry_t *bktr_get_subsection(bktr_subsection_block_t *block, uint64_t offset) {
|
||||||
/* If offset is past the virtual, we're reading from the BKTR_HEADER subsection. */
|
/* If offset is past the virtual, we're reading from the BKTR_HEADER subsection. */
|
||||||
|
@ -44,13 +55,15 @@ bktr_subsection_entry_t *bktr_get_subsection(bktr_subsection_block_t *block, uin
|
||||||
return &block->buckets[block->num_buckets - 1].entries[block->buckets[block->num_buckets - 1].num_entries];
|
return &block->buckets[block->num_buckets - 1].entries[block->buckets[block->num_buckets - 1].num_entries];
|
||||||
}
|
}
|
||||||
|
|
||||||
bktr_subsection_bucket_t *bucket = &block->buckets[0];
|
uint32_t bucket_num = 0;
|
||||||
for (unsigned int i = 1; i < block->num_buckets; i++) {
|
for (unsigned int i = 1; i < block->num_buckets; i++) {
|
||||||
if (block->bucket_physical_offsets[i] < offset) {
|
if (block->bucket_physical_offsets[i] <= offset) {
|
||||||
bucket++;
|
bucket_num++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bktr_subsection_bucket_t *bucket = bktr_get_subsection_bucket(block, bucket_num);
|
||||||
|
|
||||||
if (bucket->num_entries == 1) { /* Check for edge case, short circuit. */
|
if (bucket->num_entries == 1) { /* Check for edge case, short circuit. */
|
||||||
return &bucket->entries[0];
|
return &bucket->entries[0];
|
||||||
}
|
}
|
||||||
|
|
3
bktr.h
3
bktr.h
|
@ -69,7 +69,10 @@ typedef struct {
|
||||||
} bktr_subsection_block_t;
|
} bktr_subsection_block_t;
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
bktr_relocation_bucket_t *bktr_get_relocation_bucket(bktr_relocation_block_t *block, uint32_t i);
|
||||||
bktr_relocation_entry_t *bktr_get_relocation(bktr_relocation_block_t *block, uint64_t offset);
|
bktr_relocation_entry_t *bktr_get_relocation(bktr_relocation_block_t *block, uint64_t offset);
|
||||||
|
|
||||||
|
bktr_subsection_bucket_t *bktr_get_subsection_bucket(bktr_subsection_block_t *block, uint32_t i);
|
||||||
bktr_subsection_entry_t *bktr_get_subsection(bktr_subsection_block_t *block, uint64_t offset);
|
bktr_subsection_entry_t *bktr_get_subsection(bktr_subsection_block_t *block, uint64_t offset);
|
||||||
|
|
||||||
#endif
|
#endif
|
24
nca.c
24
nca.c
|
@ -921,13 +921,13 @@ void nca_process_bktr_section(nca_section_ctx_t *ctx) {
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
/* Allocate space for an extra (fake) relocation entry, to simplify our logic. */
|
/* Allocate space for an extra (fake) relocation entry, to simplify our logic. */
|
||||||
void *relocs = calloc(1, sb->relocation_header.size + sizeof(bktr_relocation_entry_t));
|
void *relocs = calloc(1, sb->relocation_header.size + (0x3FF0 / sizeof(uint64_t)) * sizeof(bktr_relocation_entry_t));
|
||||||
if (relocs == NULL) {
|
if (relocs == NULL) {
|
||||||
fprintf(stderr, "Failed to allocate relocation header!\n");
|
fprintf(stderr, "Failed to allocate relocation header!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
/* Allocate space for an extra (fake) subsection entry, to simplify our logic. */
|
/* Allocate space for an extra (fake) subsection entry, to simplify our logic. */
|
||||||
void *subs = calloc(1, sb->subsection_header.size + 2 * sizeof(bktr_subsection_entry_t));
|
void *subs = calloc(1, sb->subsection_header.size + (0x3FF0 / sizeof(uint64_t)) * sizeof(bktr_subsection_entry_t) + sizeof(bktr_subsection_entry_t));
|
||||||
if (subs == NULL) {
|
if (subs == NULL) {
|
||||||
fprintf(stderr, "Failed to allocate subsection header!\n");
|
fprintf(stderr, "Failed to allocate subsection header!\n");
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
|
@ -957,8 +957,24 @@ void nca_process_bktr_section(nca_section_ctx_t *ctx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This simplifies logic greatly... */
|
/* This simplifies logic greatly... */
|
||||||
bktr_relocation_bucket_t *last_reloc_bucket = &ctx->bktr_ctx.relocation_block->buckets[ctx->bktr_ctx.relocation_block->num_buckets - 1];
|
for (unsigned int i = ctx->bktr_ctx.relocation_block->num_buckets - 1; i > 0; i--) {
|
||||||
bktr_subsection_bucket_t *last_subsec_bucket = &ctx->bktr_ctx.subsection_block->buckets[ctx->bktr_ctx.subsection_block->num_buckets - 1];
|
memcpy(bktr_get_relocation_bucket(ctx->bktr_ctx.relocation_block, i), &ctx->bktr_ctx.relocation_block->buckets[i], sizeof(bktr_relocation_bucket_t));
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i + 1 < ctx->bktr_ctx.relocation_block->num_buckets; i++) {
|
||||||
|
bktr_relocation_bucket_t *cur_bucket = bktr_get_relocation_bucket(ctx->bktr_ctx.relocation_block, i);
|
||||||
|
cur_bucket->entries[cur_bucket->num_entries].virt_offset = ctx->bktr_ctx.relocation_block->bucket_virtual_offsets[i + 1];
|
||||||
|
}
|
||||||
|
for (unsigned int i = ctx->bktr_ctx.subsection_block->num_buckets - 1; i > 0; i--) {
|
||||||
|
memcpy(bktr_get_subsection_bucket(ctx->bktr_ctx.subsection_block, i), &ctx->bktr_ctx.subsection_block->buckets[i], sizeof(bktr_subsection_bucket_t));
|
||||||
|
}
|
||||||
|
for (unsigned int i = 0; i + 1 < ctx->bktr_ctx.subsection_block->num_buckets; i++) {
|
||||||
|
bktr_subsection_bucket_t *cur_bucket = bktr_get_subsection_bucket(ctx->bktr_ctx.subsection_block, i);
|
||||||
|
bktr_subsection_bucket_t *next_bucket = bktr_get_subsection_bucket(ctx->bktr_ctx.subsection_block, i+1);
|
||||||
|
cur_bucket->entries[cur_bucket->num_entries].offset = next_bucket->entries[0].offset;
|
||||||
|
cur_bucket->entries[cur_bucket->num_entries].ctr_val = next_bucket->entries[0].ctr_val;
|
||||||
|
}
|
||||||
|
bktr_relocation_bucket_t *last_reloc_bucket = bktr_get_relocation_bucket(ctx->bktr_ctx.relocation_block, ctx->bktr_ctx.relocation_block->num_buckets - 1);
|
||||||
|
bktr_subsection_bucket_t *last_subsec_bucket = bktr_get_subsection_bucket(ctx->bktr_ctx.subsection_block, ctx->bktr_ctx.subsection_block->num_buckets - 1);
|
||||||
last_reloc_bucket->entries[last_reloc_bucket->num_entries].virt_offset = ctx->bktr_ctx.relocation_block->total_size;
|
last_reloc_bucket->entries[last_reloc_bucket->num_entries].virt_offset = ctx->bktr_ctx.relocation_block->total_size;
|
||||||
last_subsec_bucket->entries[last_subsec_bucket->num_entries].offset = sb->relocation_header.offset;
|
last_subsec_bucket->entries[last_subsec_bucket->num_entries].offset = sb->relocation_header.offset;
|
||||||
last_subsec_bucket->entries[last_subsec_bucket->num_entries].ctr_val = ctx->header->section_ctr_low;
|
last_subsec_bucket->entries[last_subsec_bucket->num_entries].ctr_val = ctx->header->section_ctr_low;
|
||||||
|
|
Loading…
Reference in a new issue