-
Notifications
You must be signed in to change notification settings - Fork 23
feat: Add string-level highlighting in hex view and sync highlight to matching section string entries #8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,3 +27,46 @@ function highlightClasses(primaryClass, secondaryClass) { | |
| addPairHighlighting(secondaryElem, primaryElem); | ||
| } | ||
|
|
||
| function addStrtabSectionSyncHighlighting() { | ||
| let activeEntries = []; | ||
|
|
||
| function clearActiveEntries() { | ||
| for (let entry of activeEntries) { | ||
| entry.classList.remove("strtab_entry_active"); | ||
| } | ||
| activeEntries = []; | ||
| } | ||
|
|
||
| function getRefClass(target) { | ||
| let strElem = target.closest(".strtab_str"); | ||
|
|
||
| if (strElem === null) { | ||
| return null; | ||
| } | ||
|
|
||
| for (let cls of strElem.classList) { | ||
| if (cls.startsWith("strtab_ref")) { | ||
| return cls; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
|
|
||
| document.addEventListener("mouseover", function(event) { | ||
| let refClass = getRefClass(event.target); | ||
|
|
||
| clearActiveEntries(); | ||
|
|
||
| if (refClass === null) { | ||
| return; | ||
| } | ||
|
|
||
| let entries = document.querySelectorAll(".strtab_entry." + refClass); | ||
|
|
||
| for (let entry of entries) { | ||
| entry.classList.add("strtab_entry_active"); | ||
| activeEntries.push(entry); | ||
| } | ||
| }, false); | ||
|
Comment on lines
+56
to
+71
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -235,6 +235,18 @@ fn format_string_slice(slice: &[u8]) -> String { | |
| .fold(String::new(), |s, b| s + &format_string_byte(*b)) | ||
| } | ||
|
|
||
| fn escape_html_str(string: &str) -> String { | ||
| string.chars().fold(String::new(), |mut escaped, ch| { | ||
| if let Some(entity) = utils::html_escape(ch) { | ||
| escaped.push_str(entity); | ||
| } else { | ||
| escaped.push(ch); | ||
| } | ||
|
|
||
| escaped | ||
| }) | ||
| } | ||
|
|
||
| fn generate_note_data(o: &mut String, note: &Note) { | ||
| let name = if note.name.is_empty() { | ||
| String::new() | ||
|
|
@@ -286,8 +298,9 @@ fn generate_segment_info_table(o: &mut String, elf: &ParsedElf, phdr: &ParsedPhd | |
| } | ||
| } | ||
|
|
||
| fn generate_strtab_data(o: &mut String, section: &[u8]) { | ||
| fn generate_strtab_data(o: &mut String, section_idx: usize, section: &[u8]) { | ||
| let mut curr_start = 0; | ||
| let mut str_idx: u32 = 0; | ||
|
|
||
| w!(o, 6, "<tr>"); | ||
| w!(o, 7, "<td></td>"); | ||
|
|
@@ -302,7 +315,15 @@ fn generate_strtab_data(o: &mut String, section: &[u8]) { | |
|
|
||
| if let Ok(string) = maybe { | ||
| if section[curr_start] != 0 { | ||
| w!(o, 9, "{}", string); | ||
| w!( | ||
| o, | ||
| 9, | ||
| "<span class='strtab_entry strtab_ref{}_{}'>{}</span>", | ||
| section_idx, | ||
| str_idx, | ||
| escape_html_str(string) | ||
| ); | ||
| str_idx += 1; | ||
|
Comment on lines
+318
to
+326
|
||
| } | ||
| } | ||
|
Comment on lines
316
to
328
|
||
|
|
||
|
|
@@ -315,11 +336,11 @@ fn generate_strtab_data(o: &mut String, section: &[u8]) { | |
| w!(o, 6, "</tr>"); | ||
| } | ||
|
|
||
| fn generate_section_info_table(o: &mut String, elf: &ParsedElf, shdr: &ParsedShdr) { | ||
| fn generate_section_info_table(o: &mut String, elf: &ParsedElf, idx: usize, shdr: &ParsedShdr) { | ||
| let section = &elf.contents[shdr.file_offset..shdr.file_offset + shdr.size]; | ||
|
|
||
| if shdr.shtype == SHT_STRTAB { | ||
| generate_strtab_data(o, section); | ||
| generate_strtab_data(o, idx, section); | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -359,7 +380,7 @@ fn generate_section_info_tables(o: &mut String, elf: &ParsedElf) { | |
|
|
||
| if has_section_detail(shdr.shtype) { | ||
| w!(o, 6, "<tr><td><br></td></tr>"); | ||
| generate_section_info_table(o, elf, shdr); | ||
| generate_section_info_table(o, elf, idx, shdr); | ||
| } | ||
|
|
||
| w!(o, 5, "</table>"); | ||
|
|
@@ -415,6 +436,7 @@ fn add_highlight_script(o: &mut String) { | |
| for class in &classes { | ||
| w!(o, 3, "highlightClasses('fileinfo_{}', '{}')", class, class); | ||
| } | ||
| w!(o, 3, "addStrtabSectionSyncHighlighting();"); | ||
|
|
||
| w!(o, 2, "</script>"); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
add_strtab_rangesbuilds aVecof all string ranges (str_ranges) and then iterates again to add them toself.ranges. This can double memory usage for large string tables. You can usually avoid the temporary vector by borrowing disjoint fields (let (ranges, shdrs, contents) = (&mut self.ranges, &self.shdrs, self.contents);) and callingranges.add_range(...)directly while iterating.