Skip to content

Commit 345dbb1

Browse files
committed
Support ncp_set inside namespaces
1 parent b1ba1df commit 345dbb1

11 files changed

Lines changed: 222 additions & 240 deletions

runtime/ncp.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@
5656

5757
// NCP Variables
5858

59-
#define __ncp_main_set(opcode, address, function) void* ncp_set##opcode##_##address __attribute__((section(".ncp_set"), used)) = (void*)function;
60-
#define __ncp_ovxx_set(opcode, address, overlay, function) void* ncp_set##opcode##_##address##_ov##overlay __attribute__((section(".ncp_set"), used)) = (void*)function;
59+
#define __ncp_main_set(opcode, address, function) void* ncp_set##opcode##_##address __attribute__((section(".ncp_set" #opcode "_" #address), used)) = (void*)function;
60+
#define __ncp_ovxx_set(opcode, address, overlay, function) void* ncp_set##opcode##_##address##_ov##overlay __attribute__((section(".ncp_set" #opcode "_" #address "_ov" #overlay), used)) = (void*)function;
6161

6262
#define __ncp_main_set_jump(address, function) __ncp_main_set(jump, address, function)
6363
#define __ncp_main_set_call(address, function) __ncp_main_set(call, address, function)

source/app/application.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ VerboseTag Application::parseVerboseTag(const std::string& tagName)
392392
if (tagName == "library") return VerboseTag::Library;
393393
if (tagName == "linking") return VerboseTag::Linking;
394394
if (tagName == "symbols") return VerboseTag::Symbols;
395+
if (tagName == "nolib") return VerboseTag::NoLib;
395396
if (tagName == "all") return VerboseTag::All;
396397

397398
return static_cast<VerboseTag>(-1); // Invalid tag

source/app/application.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ enum class VerboseTag {
1818
Library, // Library dependency analysis
1919
Linking, // Linker script generation and linking process
2020
Symbols, // Symbol resolution and analysis
21+
NoLib, // Do not print lib patches
2122
All // All verbose output (equivalent to old --verbose)
2223
};
2324

source/patch/elf_analyzer.cpp

Lines changed: 48 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,23 @@ void ElfAnalyzer::gatherInfoFromElf(
7272
{
7373
if (p->sourceType == PatchSourceType::Section)
7474
{
75-
std::string_view nameAsLabel = std::string_view(p->symbol).substr(1);
76-
if (nameAsLabel == symbolName)
77-
{
78-
p->srcAddress = symbol.st_value;
79-
p->sectionIdx = symbol.st_shndx;
80-
p->symbol = nameAsLabel;
81-
}
75+
if (p->isNcpSet)
76+
{
77+
if (p->symbol == symbolName)
78+
{
79+
p->sectionIdx = symbol.st_shndx;
80+
}
81+
}
82+
else
83+
{
84+
std::string_view nameAsLabel = std::string_view(p->symbol).substr(1);
85+
if (nameAsLabel == symbolName)
86+
{
87+
p->srcAddress = symbol.st_value;
88+
p->sectionIdx = symbol.st_shndx;
89+
p->symbol = nameAsLabel;
90+
}
91+
}
8292
}
8393
else
8494
{
@@ -125,34 +135,26 @@ void ElfAnalyzer::gatherInfoFromElf(
125135
}
126136
if (sectionName.starts_with(".ncp_set"))
127137
{
128-
// found the ncp_set section, get all hook definitions stored there
129-
130-
int srcAddrOv = -1;
131-
if (sectionName.length() != 8 && sectionName.substr(8).starts_with("_ov"))
132-
{
133-
try {
134-
srcAddrOv = std::stoi(std::string(sectionName.substr(11)));
135-
} catch (std::exception& e) {
136-
Log::out << OWARN << "Found invalid overlay reading ncp_set section: " << sectionName << std::endl;
137-
return false;
138-
}
139-
}
140-
138+
// Handle ncp_set sections directly - each section corresponds to a specific patch
141139
const char* sectionData = m_elf->getSection<char>(section);
142-
140+
141+
// Find the patch that corresponds to this section
143142
for (auto& p : patchInfo)
144143
{
145-
if (p->isNcpSet && p->srcAddressOv == srcAddrOv)
144+
if (p->isNcpSet && p->symbol == sectionName)
146145
{
147-
u32 dataOffset = p->srcAddress - section.sh_addr;
148-
if (dataOffset + 4 > section.sh_size)
146+
if (section.sh_size != 4)
149147
{
150148
std::ostringstream oss;
151-
oss << "Tried to read " << OSTR(sectionName) << " data out of bounds.";
149+
oss << "ncp_set section " << OSTR(sectionName) << " should be exactly 4 bytes, but is " << section.sh_size << " bytes.";
152150
throw ncp::exception(oss.str());
153151
}
152+
153+
// Read the function pointer from the section data
154154
// ncp_set comes with the THUMB bit, we must clear it!
155-
p->srcAddress = Util::read<u32>(&sectionData[dataOffset]) & ~1;
155+
p->srcAddress = Util::read<u32>(&sectionData[0]) & ~1;
156+
// Also determine if the source function is thumb from the LSB
157+
p->srcThumb = bool(Util::read<u32>(&sectionData[0]) & 1);
156158
}
157159
}
158160
}
@@ -213,12 +215,14 @@ void ElfAnalyzer::gatherInfoFromElf(
213215

214216
if (ncp::Application::isVerbose(ncp::VerboseTag::Patch))
215217
{
216-
Log::out << ANSI_bCYAN "Patches:" ANSI_RESET "\n"
217-
<< ANSI_bWHITE "SRC_ADDR" ANSI_RESET " "
218-
<< ANSI_bWHITE "SRC_ADDR_OV" ANSI_RESET " "
218+
Log::out << ANSI_bCYAN "Patches (post-ELF analysis):" ANSI_RESET "\n"
219+
<< ANSI_bYELLOW "Note: Fields marked with * are populated/updated during ELF analysis phase" ANSI_RESET << std::endl;
220+
221+
Log::out << ANSI_bWHITE " SRC_ADDR" ANSI_RESET " "
222+
<< ANSI_bWHITE "SRC_ADDR_OV" ANSI_RESET " "
219223
<< ANSI_bWHITE "DST_ADDR" ANSI_RESET " "
220224
<< ANSI_bWHITE "DST_ADDR_OV" ANSI_RESET " "
221-
<< ANSI_bWHITE "PATCH_TYPE" ANSI_RESET " "
225+
<< ANSI_bWHITE "PATCH_TYPE" ANSI_RESET " "
222226
<< ANSI_bWHITE "SEC_IDX" ANSI_RESET " "
223227
<< ANSI_bWHITE "SEC_SIZE" ANSI_RESET " "
224228
<< ANSI_bWHITE "NCP_SET" ANSI_RESET " "
@@ -228,26 +232,28 @@ void ElfAnalyzer::gatherInfoFromElf(
228232
<< ANSI_bWHITE "SYMBOL" ANSI_RESET << std::endl;
229233
for (auto& p : patchInfo)
230234
{
231-
std::string sourceTypeStr;
232-
switch (p->sourceType) {
233-
case PatchSourceType::Section: sourceTypeStr = "section"; break;
234-
case PatchSourceType::Label: sourceTypeStr = "label"; break;
235-
case PatchSourceType::Symver: sourceTypeStr = "symver"; break;
236-
}
235+
if (ncp::Application::isVerbose(ncp::VerboseTag::NoLib) && p->unit->getType() == core::CompilationUnitType::LibraryFile)
236+
continue;
237237

238238
Log::out <<
239-
ANSI_CYAN << std::setw(8) << std::hex << p->srcAddress << ANSI_RESET " " <<
239+
ANSI_CYAN << std::setw(10) << Util::intToAddr(p->srcAddress, 8) << "*";
240+
Log::out << ANSI_RESET " " <<
240241
ANSI_YELLOW << std::setw(11) << std::dec << p->srcAddressOv << ANSI_RESET " " <<
241-
ANSI_BLUE << std::setw(8) << std::hex << p->destAddress << ANSI_RESET " " <<
242+
ANSI_BLUE << std::setw(8) << Util::intToAddr(p->destAddress, 8) << ANSI_RESET " " <<
242243
ANSI_YELLOW << std::setw(11) << std::dec << p->destAddressOv << ANSI_RESET " " <<
243244
ANSI_MAGENTA << std::setw(10) << s_patchTypeNames[p->patchType] << ANSI_RESET " " <<
244-
ANSI_WHITE << std::setw(7) << std::dec << p->sectionIdx << ANSI_RESET " " <<
245+
ANSI_WHITE << std::setw(8) << std::dec << p->sectionIdx << "*";
246+
Log::out << ANSI_RESET " " <<
245247
ANSI_WHITE << std::setw(8) << std::dec << p->sectionSize << ANSI_RESET " " <<
246248
ANSI_GREEN << std::setw(7) << std::boolalpha << p->isNcpSet << ANSI_RESET " " <<
247-
ANSI_GREEN << std::setw(9) << std::boolalpha << p->srcThumb << ANSI_RESET " " <<
249+
ANSI_GREEN << std::setw(9) << std::boolalpha << p->srcThumb;
250+
// Mark srcThumb field populated during ELF analysis for ncp_set patches
251+
Log::out << (p->isNcpSet ? "*" : " ");
252+
Log::out << ANSI_RESET " " <<
248253
ANSI_GREEN << std::setw(9) << std::boolalpha << p->destThumb << ANSI_RESET " " <<
249-
ANSI_bYELLOW << std::setw(11) << sourceTypeStr << ANSI_RESET " " <<
250-
ANSI_WHITE << p->symbol << ANSI_RESET << std::endl;
254+
ANSI_bYELLOW << std::setw(11) << toString(p->sourceType) << ANSI_RESET " " <<
255+
ANSI_WHITE << p->symbol;
256+
Log::out << ANSI_RESET << std::endl;
251257
}
252258
}
253259

source/patch/linker_script_generator.cpp

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,6 @@ void LinkerScriptGenerator::createLinkerScript(
4242
const std::vector<std::unique_ptr<GenericPatchInfo>>& patchInfo,
4343
const std::vector<std::unique_ptr<RtReplPatchInfo>>& rtreplPatches,
4444
const std::vector<std::string>& externSymbols,
45-
const std::vector<int>& destWithNcpSet,
46-
const core::CompilationUnitPtrCollection& unitsWithNcpSet,
4745
const std::vector<std::unique_ptr<OverwriteRegionInfo>>& overwriteRegions
4846
)
4947
{
@@ -95,11 +93,6 @@ void LinkerScriptGenerator::createLinkerScript(
9593
return a->destination > b->destination;
9694
});
9795

98-
std::vector<int> orderedDestWithNcpSet = destWithNcpSet;
99-
std::sort(orderedDestWithNcpSet.begin(), orderedDestWithNcpSet.end(), [](int a, int b){
100-
return a > b;
101-
});
102-
10396
for (const BuildTarget::Region* region : orderedRegions)
10497
{
10598
LDSMemoryEntry* memEntry;
@@ -147,7 +140,7 @@ void LinkerScriptGenerator::createLinkerScript(
147140
{
148141
if (ldsRegion->dest == info->unit->getTargetRegion()->destination)
149142
{
150-
if (info->sourceType == patch::PatchSourceType::Section)
143+
if (info->sourceType == patch::PatchSourceType::Section && !info->isNcpSet)
151144
{
152145
// Check if this patch's section is assigned to an overwrite region (only for final version)
153146
bool patchInOverwrite = false;
@@ -190,7 +183,12 @@ void LinkerScriptGenerator::createLinkerScript(
190183
}
191184
}
192185

193-
if (!orderedDestWithNcpSet.empty())
186+
// Check if we have any ncp_set patches
187+
bool hasNcpSetPatches = std::any_of(patchInfo.begin(), patchInfo.end(), [](const auto& info) {
188+
return info->isNcpSet;
189+
});
190+
191+
if (hasNcpSetPatches)
194192
memoryEntries.emplace_back(new LDSMemoryEntry{ "ncp_set", 0, 0x100000 });
195193

196194
std::string o;
@@ -392,30 +390,22 @@ void LinkerScriptGenerator::createLinkerScript(
392390
if (!overPatches.empty())
393391
o += '\n';
394392

395-
for (auto& p : orderedDestWithNcpSet)
393+
// Generate linker script entries for ncp_set sections
394+
for (const auto& info : patchInfo)
396395
{
397-
o += "\t.ncp_set";
398-
if (p == -1)
396+
if (info->isNcpSet)
399397
{
400-
o += " : { KEEP(* (.ncp_set)) } > ncp_set AT > bin\n\n";
398+
// Create individual section entries for each ncp_set patch
399+
o += '\t';
400+
o += info->symbol; // This is the section name like .ncp_setjump_0x02000000
401+
o += " : { KEEP(\"";
402+
o += Util::relativeIfSubpath(info->unit->getObjectPath()).string();
403+
o += "\" (";
404+
o += info->symbol;
405+
o += ")) } > ncp_set AT > bin\n";
401406
}
402-
else
403-
{
404-
o += "_ov";
405-
o += std::to_string(p);
406-
o += " : {\n";
407-
for (const auto* unit : unitsWithNcpSet)
408-
{
409-
if (unit->getTargetRegion()->destination == p)
410-
{
411-
o += "\t\t KEEP(\"";
412-
o += Util::relativeIfSubpath(unit->getObjectPath()).string();
413-
o += "\" (.ncp_set))\n\t"
414-
"} > ncp_set AT > bin\n\n";
415-
}
416-
}
417-
}
418407
}
408+
o += '\n';
419409

420410
o += "\t/DISCARD/ : {*(.*)}\n"
421411
"}\n";

source/patch/linker_script_generator.hpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,6 @@ class LinkerScriptGenerator
5151
const std::vector<std::unique_ptr<GenericPatchInfo>>& patchInfo,
5252
const std::vector<std::unique_ptr<RtReplPatchInfo>>& rtreplPatches,
5353
const std::vector<std::string>& externSymbols,
54-
const std::vector<int>& destWithNcpSet,
55-
const core::CompilationUnitPtrCollection& unitsWithNcpSet,
5654
const std::vector<std::unique_ptr<OverwriteRegionInfo>>& overwriteRegions
5755
);
5856

0 commit comments

Comments
 (0)