2018-06-04 18:10:57 +00:00
|
|
|
import gdb
|
|
|
|
import re
|
|
|
|
import gdb.printing
|
|
|
|
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
class PuTTYMpintPrettyPrinter(gdb.printing.PrettyPrinter):
|
|
|
|
"Pretty-print PuTTY's mp_int type."
|
|
|
|
name = "mp_int"
|
2018-06-04 18:10:57 +00:00
|
|
|
|
|
|
|
def __init__(self, val):
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
super(PuTTYMpintPrettyPrinter, self).__init__(self.name)
|
2018-06-04 18:10:57 +00:00
|
|
|
self.val = val
|
|
|
|
|
|
|
|
def to_string(self):
|
|
|
|
type_BignumInt = gdb.lookup_type("BignumInt")
|
|
|
|
type_BignumIntPtr = type_BignumInt.pointer()
|
|
|
|
BIGNUM_INT_BITS = 8 * type_BignumInt.sizeof
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
array = self.val["w"]
|
2018-06-04 18:10:57 +00:00
|
|
|
aget = lambda i: int(array[i]) & ((1 << BIGNUM_INT_BITS)-1)
|
|
|
|
|
|
|
|
try:
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
length = int(self.val["nw"])
|
2018-06-04 18:10:57 +00:00
|
|
|
value = 0
|
|
|
|
for i in range(length):
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
value |= aget(i) << (BIGNUM_INT_BITS * i)
|
|
|
|
return "mp_int({:#x})".format(value)
|
2018-06-04 18:10:57 +00:00
|
|
|
|
|
|
|
except gdb.MemoryError:
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
address = int(self.val)
|
2018-06-04 18:10:57 +00:00
|
|
|
if address == 0:
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
return "mp_int(NULL)".format(address)
|
|
|
|
return "mp_int(invalid @ {:#x})".format(address)
|
2018-06-04 18:10:57 +00:00
|
|
|
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
class PuTTYPrinterSelector(gdb.printing.PrettyPrinter):
|
|
|
|
def __init__(self):
|
|
|
|
super(PuTTYPrinterSelector, self).__init__("PuTTY")
|
|
|
|
def __call__(self, val):
|
|
|
|
if str(val.type) == "mp_int *":
|
|
|
|
return PuTTYMpintPrettyPrinter(val)
|
|
|
|
return None
|
2018-06-04 18:10:57 +00:00
|
|
|
|
Complete rewrite of PuTTY's bignum library.
The old 'Bignum' data type is gone completely, and so is sshbn.c. In
its place is a new thing called 'mp_int', handled by an entirely new
library module mpint.c, with API differences both large and small.
The main aim of this change is that the new library should be free of
timing- and cache-related side channels. I've written the code so that
it _should_ - assuming I haven't made any mistakes - do all of its
work without either control flow or memory addressing depending on the
data words of the input numbers. (Though, being an _arbitrary_
precision library, it does have to at least depend on the sizes of the
numbers - but there's a 'formal' size that can vary separately from
the actual magnitude of the represented integer, so if you want to
keep it secret that your number is actually small, it should work fine
to have a very long mp_int and just happen to store 23 in it.) So I've
done all my conditionalisation by means of computing both answers and
doing bit-masking to swap the right one into place, and all loops over
the words of an mp_int go up to the formal size rather than the actual
size.
I haven't actually tested the constant-time property in any rigorous
way yet (I'm still considering the best way to do it). But this code
is surely at the very least a big improvement on the old version, even
if I later find a few more things to fix.
I've also completely rewritten the low-level elliptic curve arithmetic
from sshecc.c; the new ecc.c is closer to being an adjunct of mpint.c
than it is to the SSH end of the code. The new elliptic curve code
keeps all coordinates in Montgomery-multiplication transformed form to
speed up all the multiplications mod the same prime, and only converts
them back when you ask for the affine coordinates. Also, I adopted
extended coordinates for the Edwards curve implementation.
sshecc.c has also had a near-total rewrite in the course of switching
it over to the new system. While I was there, I've separated ECDSA and
EdDSA more completely - they now have separate vtables, instead of a
single vtable in which nearly every function had a big if statement in
it - and also made the externally exposed types for an ECDSA key and
an ECDH context different.
A minor new feature: since the new arithmetic code includes a modular
square root function, we can now support the compressed point
representation for the NIST curves. We seem to have been getting along
fine without that so far, but it seemed a shame not to put it in,
since it was suddenly easy.
In sshrsa.c, one major change is that I've removed the RSA blinding
step in rsa_privkey_op, in which we randomise the ciphertext before
doing the decryption. The purpose of that was to avoid timing leaks
giving away the plaintext - but the new arithmetic code should take
that in its stride in the course of also being careful enough to avoid
leaking the _private key_, which RSA blinding had no way to do
anything about in any case.
Apart from those specific points, most of the rest of the changes are
more or less mechanical, just changing type names and translating code
into the new API.
2018-12-31 13:53:41 +00:00
|
|
|
gdb.printing.register_pretty_printer(None, PuTTYPrinterSelector())
|
2018-06-09 06:52:28 +00:00
|
|
|
|
|
|
|
class MemDumpCommand(gdb.Command):
|
|
|
|
"""Print a hex+ASCII dump of object EXP.
|
|
|
|
|
|
|
|
EXP must be an expression whose value resides in memory. The
|
|
|
|
contents of the memory it occupies are printed in a standard hex
|
|
|
|
dump format, with each line showing an offset relative to the
|
|
|
|
address of EXP, then the hex byte values of the memory at that
|
|
|
|
offset, and then a translation into ASCII of the same bytes (with
|
|
|
|
values outside the printable ASCII range translated as '.').
|
|
|
|
|
|
|
|
To dump a number of bytes from a particular address, it's useful
|
|
|
|
to use the gdb expression extensions {TYPE} and @LENGTH. For
|
|
|
|
example, if 'ptr' and 'len' are variables giving an address and a
|
|
|
|
length in bytes, then the command
|
|
|
|
|
|
|
|
memdump {char} ptr @ len
|
|
|
|
|
|
|
|
will dump the range of memory described by those two variables."""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super(MemDumpCommand, self).__init__(
|
|
|
|
"memdump", gdb.COMMAND_DATA, gdb.COMPLETE_EXPRESSION)
|
|
|
|
|
|
|
|
def invoke(self, cmdline, from_tty):
|
|
|
|
expr = gdb.parse_and_eval(cmdline)
|
|
|
|
try:
|
|
|
|
start, size = int(expr.address), expr.type.sizeof
|
|
|
|
except gdb.error as e:
|
2018-11-16 19:22:43 +00:00
|
|
|
raise gdb.GdbError(str(e))
|
2018-06-09 06:52:28 +00:00
|
|
|
except (TypeError, AttributeError):
|
2018-11-16 19:22:43 +00:00
|
|
|
raise gdb.GdbError("expression must identify an object in memory")
|
2018-06-09 06:52:28 +00:00
|
|
|
return
|
|
|
|
|
|
|
|
width = 16
|
|
|
|
line_ptr_type = gdb.lookup_type(
|
|
|
|
"unsigned char").const().array(width).pointer()
|
|
|
|
|
|
|
|
dumpaddr = 0
|
|
|
|
while size > 0:
|
|
|
|
line = gdb.Value(start).cast(line_ptr_type).dereference()
|
|
|
|
thislinelen = min(size, width)
|
|
|
|
start += thislinelen
|
|
|
|
size -= thislinelen
|
|
|
|
|
|
|
|
dumpline = [None, " "] + [" "] * width + [" "] + [""] * width
|
|
|
|
|
|
|
|
dumpline[0] = "{:08x}".format(dumpaddr)
|
|
|
|
dumpaddr += thislinelen
|
|
|
|
|
|
|
|
for i in range(thislinelen):
|
|
|
|
ch = int(line[i]) & 0xFF
|
|
|
|
dumpline[2+i] = " {:02x}".format(ch)
|
|
|
|
dumpline[3+width+i] = chr(ch) if 0x20 <= ch < 0x7F else "."
|
|
|
|
|
|
|
|
sys.stdout.write("".join(dumpline) + "\n")
|
|
|
|
|
|
|
|
MemDumpCommand()
|
2018-11-16 19:22:43 +00:00
|
|
|
|
|
|
|
class ContainerOf(gdb.Function):
|
|
|
|
"""Implement the container_of macro from PuTTY's defs.h.
|
|
|
|
|
|
|
|
Arguments are an object or pointer to object; a type to convert it
|
|
|
|
to; and, optionally the name of the structure member in the
|
|
|
|
destination type that the pointer points to. (If the member name
|
|
|
|
is not provided, then the default is whichever member of the
|
|
|
|
destination structure type has the same type as the input object,
|
|
|
|
provided there's only one.)
|
|
|
|
|
|
|
|
Due to limitations of GDB's convenience function syntax, the type
|
|
|
|
and member names must be provided as strings.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super(ContainerOf, self).__init__("container_of")
|
|
|
|
|
|
|
|
def match_type(self, obj, typ):
|
|
|
|
if obj.type == typ:
|
|
|
|
return obj
|
|
|
|
|
|
|
|
try:
|
|
|
|
ref = obj.referenced_value()
|
|
|
|
if ref.type == typ:
|
|
|
|
return ref
|
|
|
|
except gdb.error:
|
|
|
|
pass
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
def invoke(self, obj, dest_type_name_val, member_name_val=None):
|
|
|
|
try:
|
|
|
|
dest_type_name = dest_type_name_val.string()
|
|
|
|
except gdb.error:
|
|
|
|
raise gdb.GdbError("destination type name must be a string")
|
|
|
|
|
|
|
|
try:
|
|
|
|
dest_type = gdb.lookup_type(dest_type_name)
|
|
|
|
except gdb.error:
|
|
|
|
raise gdb.GdbError("no such type '{dt}'".format(dt=dest_type_name))
|
|
|
|
|
|
|
|
if member_name_val is not None:
|
|
|
|
try:
|
|
|
|
member_name = member_name_val.string()
|
|
|
|
except gdb.error:
|
|
|
|
raise gdb.GdbError("member name must be a string")
|
|
|
|
|
|
|
|
for field in dest_type.fields():
|
|
|
|
if field.name == member_name:
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
raise gdb.GdbError(
|
|
|
|
"type '{dt}' has no member called '{memb}'"
|
|
|
|
.format(dt=dest_type_name, memb=member_name))
|
|
|
|
|
|
|
|
match_obj = self.match_type(obj, field.type)
|
|
|
|
else:
|
|
|
|
matches = []
|
|
|
|
|
|
|
|
for field in dest_type.fields():
|
|
|
|
this_match_obj = self.match_type(obj, field.type)
|
|
|
|
if this_match_obj is not None:
|
|
|
|
match_obj = this_match_obj
|
|
|
|
matches.append(field)
|
|
|
|
|
|
|
|
if len(matches) == 0:
|
|
|
|
raise gdb.GdbError(
|
|
|
|
"type '{dt}' has no member matching type '{ot}'"
|
|
|
|
.format(dt=dest_type_name, ot=obj.type))
|
|
|
|
|
|
|
|
if len(matches) > 1:
|
|
|
|
raise gdb.GdbError(
|
|
|
|
"type '{dt}' has multiple members matching type '{ot}'"
|
|
|
|
" ({memberlist})"
|
|
|
|
.format(dt=dest_type_name, ot=obj.type,
|
|
|
|
memberlist=", ".join(f.name for f in matches)))
|
|
|
|
|
|
|
|
field = matches[0]
|
|
|
|
|
|
|
|
if field.bitpos % 8 != 0:
|
|
|
|
raise gdb.GdbError(
|
|
|
|
"offset of field '{memb}' is a fractional number of bytes"
|
|
|
|
.format(dt=dest_type_name, memb=member_name))
|
|
|
|
offset = field.bitpos // 8
|
|
|
|
|
|
|
|
if match_obj.type != field.type:
|
|
|
|
raise gdb.GdbError(
|
|
|
|
"value to convert does not have type '{ft}'"
|
|
|
|
.format(ft=field.type))
|
|
|
|
|
|
|
|
try:
|
|
|
|
addr = int(match_obj.address)
|
|
|
|
except gdb.error:
|
|
|
|
raise gdb.GdbError("cannot take address of value to convert")
|
|
|
|
|
|
|
|
return gdb.Value(addr - offset).cast(dest_type.pointer())
|
|
|
|
|
|
|
|
ContainerOf()
|
|
|
|
|
|
|
|
class List234(gdb.Function):
|
|
|
|
"""List the elements currently stored in a tree234.
|
|
|
|
|
|
|
|
Arguments are a tree234, and optionally a value type. If no value
|
|
|
|
type is given, the result is a list of the raw void * pointers
|
|
|
|
stored in the tree. Othewise, each one is cast to a pointer to the
|
|
|
|
value type and dereferenced.
|
|
|
|
|
|
|
|
Due to limitations of GDB's convenience function syntax, the value
|
|
|
|
type must be provided as a string.
|
|
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
def __init__(self):
|
|
|
|
super(List234, self).__init__("list234")
|
|
|
|
|
|
|
|
def add_elements(self, node, destlist):
|
|
|
|
kids = node["kids"]
|
|
|
|
elems = node["elems"]
|
|
|
|
for i in range(4):
|
|
|
|
if int(kids[i]) != 0:
|
|
|
|
add_elements(self, kids[i].dereference(), destlist)
|
|
|
|
if i < 3 and int(elems[i]) != 0:
|
|
|
|
destlist.append(elems[i])
|
|
|
|
|
|
|
|
def invoke(self, tree, value_type_name_val=None):
|
|
|
|
if value_type_name_val is not None:
|
|
|
|
try:
|
|
|
|
value_type_name = value_type_name_val.string()
|
|
|
|
except gdb.error:
|
|
|
|
raise gdb.GdbError("value type name must be a string")
|
|
|
|
|
|
|
|
try:
|
|
|
|
value_type = gdb.lookup_type(value_type_name)
|
|
|
|
except gdb.error:
|
|
|
|
raise gdb.GdbError("no such type '{dt}'"
|
|
|
|
.format(dt=value_type_name))
|
|
|
|
else:
|
|
|
|
value_type = None
|
|
|
|
|
|
|
|
try:
|
|
|
|
tree = tree.dereference()
|
|
|
|
except gdb.error:
|
|
|
|
pass
|
|
|
|
|
|
|
|
if tree.type == gdb.lookup_type("tree234"):
|
|
|
|
tree = tree["root"].dereference()
|
|
|
|
|
|
|
|
if tree.type != gdb.lookup_type("node234"):
|
|
|
|
raise gdb.GdbError(
|
|
|
|
"input value is not a tree234")
|
|
|
|
|
|
|
|
if int(tree.address) == 0:
|
|
|
|
# If you try to return {} for the empty list, gdb gives
|
|
|
|
# the cryptic error "bad array bounds (0, -1)"! We return
|
|
|
|
# NULL as the best approximation to 'sorry, list is
|
|
|
|
# empty'.
|
|
|
|
return gdb.parse_and_eval("((void *)0)")
|
|
|
|
|
|
|
|
elems = []
|
|
|
|
self.add_elements(tree, elems)
|
|
|
|
|
|
|
|
if value_type is not None:
|
|
|
|
value_ptr_type_name = str(value_type.pointer())
|
|
|
|
elem_fmt = lambda p: "*({}){}".format(value_ptr_type_name, int(p))
|
|
|
|
else:
|
|
|
|
elem_fmt = lambda p: "(void *){}".format(int(p))
|
|
|
|
|
|
|
|
elems_str = "{" + ",".join(elem_fmt(elem) for elem in elems) + "}"
|
|
|
|
return gdb.parse_and_eval(elems_str)
|
|
|
|
|
|
|
|
List234()
|