@@ -156,14 +156,14 @@ BNSegmentFlag SegmentFlagsFromMachOProtections(int initProt, int maxProt) {
156156
157157#pragma clang diagnostic push
158158#pragma clang diagnostic ignored "-Wunused-function"
159- static int64_t readSLEB128 (DataBuffer& buffer, size_t length, size_t & offset )
159+ static int64_t readSLEB128 (const uint8_t *& current, const uint8_t * end )
160160{
161161 uint8_t cur;
162162 int64_t value = 0 ;
163163 size_t shift = 0 ;
164- while (offset < length )
164+ while (current != end )
165165 {
166- cur = buffer[offset++] ;
166+ cur = *current++ ;
167167 value |= (cur & 0x7f ) << shift;
168168 shift += 7 ;
169169 if ((cur & 0x80 ) == 0 )
@@ -175,16 +175,16 @@ static int64_t readSLEB128(DataBuffer& buffer, size_t length, size_t& offset)
175175#pragma clang diagnostic pop
176176
177177
178- static uint64_t readLEB128 (DataBuffer& p, size_t end, size_t & offset )
178+ static uint64_t readLEB128 (const uint8_t *& current, const uint8_t * end )
179179{
180180 uint64_t result = 0 ;
181181 int bit = 0 ;
182182 do
183183 {
184- if (offset >= end)
184+ if (current >= end)
185185 return -1 ;
186186
187- uint64_t slice = p[offset] & 0x7f ;
187+ uint64_t slice = *current & 0x7f ;
188188
189189 if (bit > 63 )
190190 return -1 ;
@@ -193,14 +193,14 @@ static uint64_t readLEB128(DataBuffer& p, size_t end, size_t& offset)
193193 result |= (slice << bit);
194194 bit += 7 ;
195195 }
196- } while (p[offset++] & 0x80 );
196+ } while (*current++ & 0x80 );
197197 return result;
198198}
199199
200200
201- uint64_t readValidULEB128 (DataBuffer& buffer, size_t & cursor )
201+ uint64_t readValidULEB128 (const uint8_t *& current, const uint8_t * end )
202202{
203- uint64_t value = readLEB128 (buffer, buffer. GetLength (), cursor );
203+ uint64_t value = readLEB128 (current, end );
204204 if ((int64_t )value == -1 )
205205 throw ReadException ();
206206 return value;
@@ -2281,7 +2281,7 @@ std::optional<SharedCacheMachOHeader> SharedCache::LoadHeaderForAddress(std::sha
22812281}
22822282
22832283void SharedCache::InitializeHeader (
2284- Ref<BinaryView> view, VM* vm, SharedCacheMachOHeader header, std::vector<MemoryRegion*> regionsToLoad)
2284+ Ref<BinaryView> view, VM* vm, const SharedCacheMachOHeader& header, std::vector<MemoryRegion*> regionsToLoad)
22852285{
22862286 WillMutateState ();
22872287
@@ -2552,9 +2552,11 @@ void SharedCache::InitializeHeader(
25522552 uint64_t curfunc = header.textBase ;
25532553 uint64_t curOffset;
25542554
2555- while (i < header.functionStarts .funcsize )
2555+ auto current = static_cast <const uint8_t *>(funcStarts.GetData ());
2556+ auto end = current + funcStarts.GetLength ();
2557+ while (current != end)
25562558 {
2557- curOffset = readLEB128 (funcStarts, header. functionStarts . funcsize , i );
2559+ curOffset = readLEB128 (current, end );
25582560 bool addFunction = false ;
25592561 for (const auto & region : regionsToLoad)
25602562 {
@@ -2709,98 +2711,94 @@ void SharedCache::InitializeHeader(
27092711 }
27102712}
27112713
2712- struct ExportNode
2713- {
2714- std::string text;
2715- uint64_t offset;
2716- uint64_t flags;
2717- };
2718-
27192714
2720- void SharedCache::ReadExportNode (std::vector<Ref<Symbol>>& symbolList, SharedCacheMachOHeader& header, DataBuffer& buffer, uint64_t textBase ,
2721- const std::string& currentText, size_t cursor, uint32_t endGuard )
2715+ void SharedCache::ReadExportNode (std::vector<Ref<Symbol>>& symbolList, const SharedCacheMachOHeader& header,
2716+ const uint8_t * begin, const uint8_t * end, const uint8_t * current, uint64_t textBase, const std::string& currentText )
27222717{
2723-
2724- if (cursor > endGuard)
2718+ if (current >= end)
27252719 throw ReadException ();
27262720
2727- uint64_t terminalSize = readValidULEB128 (buffer, cursor );
2728- uint64_t childOffset = cursor + terminalSize;
2721+ uint64_t terminalSize = readValidULEB128 (current, end );
2722+ const uint8_t * child = current + terminalSize;
27292723 if (terminalSize != 0 ) {
27302724 uint64_t imageOffset = 0 ;
2731- uint64_t flags = readValidULEB128 (buffer, cursor );
2725+ uint64_t flags = readValidULEB128 (current, end );
27322726 if (!(flags & EXPORT_SYMBOL_FLAGS_REEXPORT))
27332727 {
2734- imageOffset = readValidULEB128 (buffer, cursor );
2735- auto symbolType = m_dscView-> GetAnalysisFunctionsForAddress (textBase + imageOffset). size () ? FunctionSymbol : DataSymbol;
2728+ imageOffset = readValidULEB128 (current, end );
2729+ if (!currentText. empty () && textBase + imageOffset)
27362730 {
2737- if (!currentText.empty () && textBase + imageOffset)
2731+ uint32_t flags;
2732+ BNSymbolType type;
2733+ for (auto s : header.sections )
27382734 {
2739- uint32_t flags;
2740- BNSymbolType type;
2741- for (auto s : header.sections )
2735+ if (s.addr < textBase + imageOffset)
27422736 {
2743- if (s.addr < textBase + imageOffset)
2737+ if (s.addr + s. size > textBase + imageOffset)
27442738 {
2745- if (s.addr + s.size > textBase + imageOffset)
2746- {
2747- flags = s.flags ;
2748- }
2739+ flags = s.flags ;
2740+ break ;
27492741 }
27502742 }
2751- if ((flags & S_ATTR_PURE_INSTRUCTIONS) == S_ATTR_PURE_INSTRUCTIONS
2752- || (flags & S_ATTR_SOME_INSTRUCTIONS) == S_ATTR_SOME_INSTRUCTIONS)
2753- type = FunctionSymbol;
2754- else
2755- type = DataSymbol;
2743+ }
2744+ if ((flags & S_ATTR_PURE_INSTRUCTIONS) == S_ATTR_PURE_INSTRUCTIONS
2745+ || (flags & S_ATTR_SOME_INSTRUCTIONS) == S_ATTR_SOME_INSTRUCTIONS)
2746+ type = FunctionSymbol;
2747+ else
2748+ type = DataSymbol;
27562749
27572750#if EXPORT_TRIE_DEBUG
2758- // BNLogInfo("export: %s -> 0x%llx", n.text.c_str(), image.baseAddress + n.offset);
2751+ // BNLogInfo("export: %s -> 0x%llx", n.text.c_str(), image.baseAddress + n.offset);
27592752#endif
2760- auto sym = new Symbol (type, currentText, textBase + imageOffset);
2761- symbolList.push_back (sym);
2762- }
2753+ // TODO: The usual `Symbol` constructors take a `NameSpace` and do unnecessary memory allocations
2754+ // to pass its fields down to the core API. Here we pass nullptr for the namespace which is treated
2755+ // the same, but avoids the memory allocations. Switch back to directly constructing a `Symbol`
2756+ // once it gains constructors without that overhead.
2757+ auto symbol = new Symbol (BNCreateSymbol (type, currentText.c_str (), currentText.c_str (),
2758+ currentText.c_str (), textBase + imageOffset, NoBinding, nullptr , 0 ));
2759+ symbolList.push_back (symbol);
27632760 }
27642761 }
27652762 }
2766- cursor = childOffset;
2767- uint8_t childCount = buffer[cursor];
2768- cursor++;
2769- if (cursor > endGuard)
2770- throw ReadException ();
2763+ current = child;
2764+ uint8_t childCount = *current++;
2765+ std::string childText = currentText;
27712766 for (uint8_t i = 0 ; i < childCount; ++i)
27722767 {
2773- std::string childText;
2774- while (buffer[cursor] != 0 & cursor <= endGuard)
2775- childText.push_back (buffer[cursor++]);
2776- cursor++;
2777- if (cursor > endGuard)
2768+ if (current >= end)
2769+ throw ReadException ();
2770+ auto it = std::find (current, end, 0 );
2771+ childText.append (current, it);
2772+ current = it + 1 ;
2773+ if (current >= end)
27782774 throw ReadException ();
2779- auto next = readValidULEB128 (buffer, cursor );
2775+ auto next = readValidULEB128 (current, end );
27802776 if (next == 0 )
27812777 throw ReadException ();
2782- ReadExportNode (symbolList, header, buffer, textBase, currentText + childText, next, endGuard);
2778+ ReadExportNode (symbolList, header, begin, end, begin + next, textBase, childText);
2779+ childText.resize (currentText.size ());
27832780 }
27842781}
27852782
27862783
2787- std::vector<Ref<Symbol>> SharedCache::ParseExportTrie (std::shared_ptr<MMappedFileAccessor> linkeditFile, SharedCacheMachOHeader header)
2784+ std::vector<Ref<Symbol>> SharedCache::ParseExportTrie (std::shared_ptr<MMappedFileAccessor> linkeditFile, const SharedCacheMachOHeader& header)
27882785{
2789- std::vector<Ref<Symbol>> symbols;
2786+ if (!header.exportTrie .datasize ) {
2787+ return {};
2788+ }
2789+
27902790 try
27912791 {
2792- auto reader = linkeditFile;
2793-
2794- std::vector<ExportNode> nodes;
2795-
2796- DataBuffer buffer = reader->ReadBuffer (header.exportTrie .dataoff , header.exportTrie .datasize );
2797- ReadExportNode (symbols, header, buffer, header.textBase , " " , 0 , header.exportTrie .datasize );
2792+ std::vector<Ref<Symbol>> symbols;
2793+ auto [begin, end] = linkeditFile->ReadSpan (header.exportTrie .dataoff , header.exportTrie .datasize );
2794+ ReadExportNode (symbols, header, begin, end, begin, header.textBase , " " );
2795+ return symbols;
27982796 }
27992797 catch (std::exception& e)
28002798 {
28012799 BNLogError (" Failed to load Export Trie" );
2800+ return {};
28022801 }
2803- return symbols;
28042802}
28052803
28062804std::vector<std::string> SharedCache::GetAvailableImages ()
0 commit comments