mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-25 16:50:15 +00:00
LDR: CRO linked list structure
This commit is contained in:
parent
469172c5c0
commit
0234bf0f34
@ -349,6 +349,44 @@ class CROHelper final {
|
||||
return entry.offset + segment_tag.offset_into_segment;
|
||||
}
|
||||
|
||||
VAddr Next() const {
|
||||
return GetField(NextCRO);
|
||||
}
|
||||
|
||||
VAddr Previous() const {
|
||||
return GetField(PreviousCRO);
|
||||
}
|
||||
|
||||
void SetNext(VAddr next) {
|
||||
SetField(NextCRO, next);
|
||||
}
|
||||
|
||||
void SetPrevious(VAddr previous) {
|
||||
SetField(PreviousCRO, previous);
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function iterating over all registered auto-link modules, including the static module.
|
||||
* @param crs_address the virtual address of the static module
|
||||
* @param func a function object to operate on a module. It accepts one parameter
|
||||
* CROHelper and returns ResultVal<bool>. It should return true to continue the iteration,
|
||||
* false to stop the iteration, or an error code (which will also stop the iteration).
|
||||
* @returns ResultCode indicating the result of the operation, RESULT_SUCCESS if all iteration success,
|
||||
* otherwise error code of the last iteration.
|
||||
*/
|
||||
template <typename FunctionObject>
|
||||
static ResultCode ForEachAutoLinkCRO(VAddr crs_address, FunctionObject func) {
|
||||
VAddr current = crs_address;
|
||||
while (current) {
|
||||
CROHelper cro(current);
|
||||
CASCADE_RESULT(bool next, func(cro));
|
||||
if (!next)
|
||||
break;
|
||||
current = cro.Next();
|
||||
}
|
||||
return RESULT_SUCCESS;
|
||||
}
|
||||
|
||||
public:
|
||||
explicit CROHelper(VAddr cro_address) : address(cro_address) {
|
||||
}
|
||||
@ -361,6 +399,95 @@ public:
|
||||
return GetField(FileSize);
|
||||
}
|
||||
|
||||
void InitCRS() {
|
||||
SetNext(0);
|
||||
SetPrevious(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers this module and adds it to the module list.
|
||||
* @param crs_address the virtual address of the static module
|
||||
* @auto_link whether to register as an auto link module
|
||||
*/
|
||||
void Register(VAddr crs_address, bool auto_link) {
|
||||
CROHelper crs(crs_address);
|
||||
CROHelper head(auto_link ? crs.Next() : crs.Previous());
|
||||
|
||||
if (head.address) {
|
||||
// there are already CROs registered
|
||||
// register as the new tail
|
||||
CROHelper tail(head.Previous());
|
||||
|
||||
// link with the old tail
|
||||
ASSERT(tail.Next() == 0);
|
||||
SetPrevious(tail.address);
|
||||
tail.SetNext(address);
|
||||
|
||||
// set previous of the head pointing to the new tail
|
||||
head.SetPrevious(address);
|
||||
} else {
|
||||
// register as the first CRO
|
||||
// set previous to self as tail
|
||||
SetPrevious(address);
|
||||
|
||||
// set self as head
|
||||
if (auto_link)
|
||||
crs.SetNext(address);
|
||||
else
|
||||
crs.SetPrevious(address);
|
||||
}
|
||||
|
||||
// the new one is the tail
|
||||
SetNext(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Unregisters this module and removes from the module list.
|
||||
* @param crs_address the virtual address of the static module
|
||||
*/
|
||||
void Unregister(VAddr crs_address) {
|
||||
CROHelper crs(crs_address);
|
||||
CROHelper next_head(crs.Next()), previous_head(crs.Previous());
|
||||
CROHelper next(Next()), previous(Previous());
|
||||
|
||||
if (address == next_head.address || address == previous_head.address) {
|
||||
// removing head
|
||||
if (next.address) {
|
||||
// the next is new head
|
||||
// let its previous point to the tail
|
||||
next.SetPrevious(previous.address);
|
||||
}
|
||||
|
||||
// set new head
|
||||
if (address == previous_head.address) {
|
||||
crs.SetPrevious(next.address);
|
||||
} else {
|
||||
crs.SetNext(next.address);
|
||||
}
|
||||
} else if (next.address) {
|
||||
// link previous and next
|
||||
previous.SetNext(next.address);
|
||||
next.SetPrevious(previous.address);
|
||||
} else {
|
||||
// removing tail
|
||||
// set previous as new tail
|
||||
previous.SetNext(0);
|
||||
|
||||
// let head's previous point to the new tail
|
||||
if (next_head.address && next_head.Previous() == address) {
|
||||
next_head.SetPrevious(previous.address);
|
||||
} else if (previous_head.address && previous_head.Previous() == address) {
|
||||
previous_head.SetPrevious(previous.address);
|
||||
} else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
// unlink self
|
||||
SetNext(0);
|
||||
SetPrevious(0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
std::array<int, 17> CROHelper::ENTRY_SIZE {{
|
||||
|
Loading…
Reference in New Issue
Block a user