Skip to content
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

Fix 'context_regs' not showing regs in order #989

Closed
wants to merge 3 commits into from

Conversation

BarryStokes
Copy link

@BarryStokes BarryStokes commented Aug 15, 2023

Description

Reverted from set to list comprehension so ordering of requested registers is maintained.
Ordering of registers is based on the order provided. The default will use gef.arch.all_registers which is correctly ordered, and the order provided by the user if manually called.
Changed so that if all requested registers are invalid it returns nothing rather than every register.

Patch required as previous change meant registers were placed into an unsorted set object leading to indeterminate ordering.

Checklist

  • My code follows the code style of this project.
  • My change includes a change to the documentation, if required.
  • If my change adds new code, adequate tests have been added.
  • I have read and agree to the CONTRIBUTING document.

fixes #986

@@ -7354,10 +7353,10 @@ def context_title(self, m: Optional[str]) -> None:

def context_regs(self) -> None:
self.context_title("registers")
ignored_registers = set(self["ignore_registers"].split())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can still be a set

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What value is there in converting to a set from what split returns?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x not in ignored_registers is faster if ignored_registers is a set.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume that there is some overhead to turning it into a set in the first place as it will need to hash all the entries. Is the saving from then comparing against a set significant enough that it's worth doing so?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

depends on the number of ignored registers, which we don't know since it is controlled by the user.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order to compare against a set, the value being compared will either need to be directly compared by value (at which point the set is needless overhead) or the value will need to be hashed, compared by hash, and then compared by value if the hashes match (unless the hashes are guaranteed to not collide, which seems unlikely). I'm currently struggling to see a scenario where making this a set does anything but increase processing overhead.

Copy link
Collaborator

@Grazfather Grazfather Aug 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you use not in ignored_registers you not only need to compare (or hash) but you also need to iterate the whole list and compare EACH, unless you use a set.

If you [reg for reg in gef.arch.all_registers if reg not in ignored_registers] and all_registers is 20 elements, but ignored_registers is, say, 1 billion then you have to do 20x1billion/2 comparisons with a list, and 20x1 with a set. Sure, this is contrived, but it's still O(NxM) vs O(N)

gef.py Show resolved Hide resolved
@Grazfather Grazfather mentioned this pull request Aug 15, 2023
4 tasks
@@ -7354,10 +7353,10 @@ def context_title(self, m: Optional[str]) -> None:

def context_regs(self) -> None:
self.context_title("registers")
ignored_registers = set(self["ignore_registers"].split())
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

x not in ignored_registers is faster if ignored_registers is a set.

gef.py Outdated Show resolved Hide resolved
removed a `ignored_registers` which was left by mistake
@Grazfather Grazfather changed the title Revert set to list for registers Fix 'context_regs' not showing regs in order Aug 15, 2023
gef.py Show resolved Hide resolved
gef.py Outdated
all_regs = gef.arch.all_registers
requested_regs = args.registers
regs = [reg for reg in requested_regs if x in all_regs]
invalid_regs = [reg for reg in requested_regs if x not in all_regs]
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can use set logic

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
invalid_regs = [reg for reg in requested_regs if x not in all_regs]
invalid_regs = set(requested_regs) - set(all_regs)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Without evidence that the process of turning into a set and then doing set operations is noticeably more performant, it doesn't seem to be worth changing to a set just so we have a set. It doesn't feel like adds any clarity and I suspect it doesn't add any performance either.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me be the one who decides that.

gef.py Show resolved Hide resolved
@Grazfather
Copy link
Collaborator

Please feel free to profile the differences - I suspect they are negligible. You can see how we profile in the context perf script https://github.com/hugsy/gef/blob/main/tests/perf/context_times.sh

@hugsy
Copy link
Owner

hugsy commented Aug 16, 2023

Closing this as it was fixed by #993

@hugsy hugsy closed this Aug 16, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Bug] Changes made in commit #81ee52d mean that register order is no longer maintained in context
3 participants