Skip to content

Commit 078de6d

Browse files
committed
Fix segment allocation
1 parent 81c36bf commit 078de6d

File tree

5 files changed

+43
-23
lines changed

5 files changed

+43
-23
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ set(CMAKE_C_STANDARD 11)
55
set(CMAKE_C_STANDARD_REQUIRED ON)
66
project(dl)
77

8-
CPMAddPackage("gh:kynex7510/CTRL#3b5ed7e")
8+
CPMAddPackage("gh:kynex7510/CTRL#f6a7f12")
99

1010
set(DL_SOURCES
1111
Source/API.c

Source/API.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <CTRL/App.h>
2+
#include <CTRL/Memory.h>
23

34
#include "Handle.h"
45
#include "Error.h"
@@ -246,7 +247,7 @@ bool ctrdlInfo(void* handle, CTRDLInfo* info) {
246247
}
247248

248249
info->base = h->base;
249-
info->size = h->size;
250+
info->size = ctrlNumPagesToSize(h->numPages);
250251

251252
ctrdl_unlockHandle(h);
252253
return success;

Source/Handle.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#include <CTRL/Memory.h>
2+
13
#include "Handle.h"
24
#include "Error.h"
35
#include "Loader.h"
@@ -157,7 +159,7 @@ CTRDLHandle* ctrdl_createHandle(const char* path, size_t flags) {
157159
handle->path = pathCopy;
158160
handle->base = 0;
159161
handle->origin = 0;
160-
handle->size = 0;
162+
handle->numPages = 0;
161163
handle->refc = 1;
162164
handle->flags = flags;
163165
memset(handle->deps, 0, sizeof(void*) * CTRDL_MAX_DEPS);
@@ -237,7 +239,8 @@ CTRDLHandle* ctrdl_unsafeFindHandleByAddr(u32 addr) {
237239

238240
for (size_t i = 0; i < ctrdl_unsafeNumHandles(); ++i) {
239241
CTRDLHandle* h = ctrdl_unsafeGetHandleByIndex(i);
240-
if ((addr >= h->base) && (addr <= (h->base + h->size))) {
242+
const size_t size = ctrlNumPagesToSize(h->numPages);
243+
if ((addr >= h->base) && (addr <= (h->base + size))) {
241244
found = h;
242245
break;
243246
}

Source/Handle.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ typedef struct {
1414
char* path; // Object path.
1515
u32 base; // Mirror address of mapped region.
1616
u32 origin; // Original address of mapped region.
17-
size_t size; // Size of mapped region.
17+
size_t numPages; // Size of mapped region in pages.
1818
size_t refc; // Object refcount.
1919
size_t flags; // Object flags.
2020
void* deps[CTRDL_MAX_DEPS]; // Object dependencies.

Source/Loader.c

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
121121
return false;
122122
}
123123

124-
// Calculate allocation space for load segments.
124+
// Get segments.
125125
const size_t numSegments = ctrdl_getELFNumSegmentsByType(&ldrData->elf, PT_LOAD);
126126
if (!numSegments) {
127127
ctrdl_setLastError(Err_InvalidObject);
@@ -144,6 +144,10 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
144144
return false;
145145
}
146146

147+
// Calculate allocation size, we assume segments are contiguous and non-overlapping.
148+
u32 lowestAddr = -1;
149+
size_t highestAddr = 0;
150+
147151
for (size_t i = 0; i < numSegments; ++i) {
148152
const Elf32_Phdr* segment = &loadSegments[i];
149153

@@ -154,18 +158,28 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
154158
return false;
155159
}
156160

157-
if (segment->p_align > 1) {
158-
handle->size += ctrlAlignSize(segment->p_memsz, segment->p_align);
159-
} else {
160-
handle->size += segment->p_memsz;
161-
}
161+
const u32 virtualBegin = ctrlAlignDown(segment->p_vaddr, CTRL_PAGE_SIZE);
162+
if (virtualBegin < lowestAddr)
163+
lowestAddr = virtualBegin;
164+
165+
const size_t endAlignment = segment->p_align > CTRL_PAGE_SIZE ? segment->p_align : CTRL_PAGE_SIZE;
166+
const u32 virtualEnd = ctrlAlignUp(segment->p_vaddr + segment->p_memsz, endAlignment);
167+
168+
if (virtualEnd > highestAddr)
169+
highestAddr = virtualEnd;
170+
}
171+
172+
if (highestAddr <= lowestAddr) {
173+
ctrdl_setLastError(Err_InvalidObject);
174+
ctrdl_unloadObject(handle);
175+
free(loadSegments);
176+
return false;
162177
}
163178

164-
handle->size = ctrlAlignSize(handle->size, CTRL_PAGE_SIZE);
179+
handle->numPages = ctrlSizeToNumPages(highestAddr - lowestAddr);
165180

166-
// Allocate and map segments.
167-
const size_t numPages = ctrlAlignSize(handle->size, CTRL_PAGE_SIZE) >> 12;
168-
if (R_FAILED(ctrlAllocCodePages(numPages, &handle->origin))) {
181+
// Allocate memory and map segments.
182+
if (R_FAILED(ctrlAllocCodePages(handle->numPages, &handle->origin))) {
169183
ctrdl_setLastError(Err_NoMemory);
170184
ctrdl_unloadObject(handle);
171185
free(loadSegments);
@@ -190,14 +204,14 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
190204
}
191205
}
192206

193-
if (R_FAILED(ctrlCommitCodePages(handle->origin, numPages, &handle->base))) {
207+
if (R_FAILED(ctrlCommitCodePages(handle->origin, handle->numPages, &handle->base))) {
194208
ctrdl_setLastError(Err_MapFailed);
195209
ctrdl_unloadObject(handle);
196210
free(loadSegments);
197211
return false;
198212
}
199213

200-
if (R_FAILED(ctrlChangeMemoryPerms(handle->base, numPages << 12, MEMPERM_READWRITE))) {
214+
if (R_FAILED(ctrlChangeMemoryPerms(handle->base, ctrlNumPagesToSize(handle->numPages), MEMPERM_READWRITE))) {
201215
ctrdl_setLastError(Err_MapFailed);
202216
ctrdl_unloadObject(handle);
203217
free(loadSegments);
@@ -216,7 +230,11 @@ static bool ctrdl_mapObject(LdrData* ldrData) {
216230
for (size_t i = 0; i < numSegments; ++i) {
217231
const Elf32_Phdr* segment = &loadSegments[i];
218232
const u32 base = handle->base + segment->p_vaddr;
219-
const size_t alignedSize = ctrlAlignSize(segment->p_memsz, segment->p_align);
233+
234+
size_t alignedSize = segment->p_memsz;
235+
if (segment->p_align > 1)
236+
alignedSize = ctrlAlignUp(alignedSize, segment->p_align);
237+
220238
const MemPerm perms = ctrdl_wrapPerms(segment->p_flags);
221239

222240
if (R_FAILED(ctrlChangeMemoryPerms(base, alignedSize, perms))) {
@@ -301,10 +319,8 @@ bool ctrdl_unloadObject(CTRDLHandle* handle) {
301319
}
302320

303321
// Unmap segments.
304-
const size_t numPages = ctrlAlignSize(handle->size, CTRL_PAGE_SIZE) >> 12;
305-
306322
if (handle->base && handle->origin) {
307-
if (R_FAILED(ctrlReleaseCodePages(handle->origin, handle->base, numPages))) {
323+
if (R_FAILED(ctrlReleaseCodePages(handle->origin, handle->base, handle->numPages))) {
308324
ctrdl_setLastError(Err_FreeFailed);
309325
return false;
310326
}
@@ -313,13 +329,13 @@ bool ctrdl_unloadObject(CTRDLHandle* handle) {
313329
}
314330

315331
if (handle->origin) {
316-
if (R_FAILED(ctrlFreeCodePages(handle->origin, numPages))) {
332+
if (R_FAILED(ctrlFreeCodePages(handle->origin, handle->numPages))) {
317333
ctrdl_setLastError(Err_FreeFailed);
318334
return false;
319335
}
320336

321337
handle->origin = 0;
322-
handle->size = 0;
338+
handle->numPages = 0;
323339
}
324340

325341
// Unload dependencies.

0 commit comments

Comments
 (0)