n = @Py2DictObject(op)->ma_mask;
for (i = 0; i < n; i++) {
entry_ptr = &@Py2DictObject(op)->ma_table[i]
- if (entry_ptr->me_key == 0 || entry_ptr->me_value == 0
- || ! @Py2String_Check(entry_ptr->me_key))
+ if (@Py2DictEntry(entry_ptr)->me_key == 0
+ || @Py2DictEntry(entry_ptr)->me_value == 0
+ || ! @Py2String_Check(@Py2DictEntry(entry_ptr)->me_key))
continue
- if (Py2String_AsString(entry_ptr->me_key) == key)
- return entry_ptr->me_value
+ if (Py2String_AsString(@Py2DictEntry(entry_ptr)->me_key) == key)
+ return @Py2DictEntry(entry_ptr)->me_value
+ }
+ return 0
+}
+
+# This function isn't really based on a function in dictobject.c, but
+# it is based on Py2Dict_GetItem().
+private function Py2Dict_GetItem_FromLong:long(op:long, key:long)
+{
+ if (!@Py2Dict_Check(op)) {
+ error(sprintf("Py2Dict_GetItem called on %s object at %p\n",
+ python2_get_typename(op), @__pointer(op)))
+ return 0
+ }
+ // We'd like to hash 'key' here, but we can't (easily). Python
+ // randomizes its hash function at python process startup. So,
+ // instead of hashing the key and then searching for that hash in
+ // the dictionary, we'll do a linear search of the dictionary for
+ // the key.
+ n = @Py2DictObject(op)->ma_mask;
+ for (i = 0; i < n; i++) {
+ entry_ptr = &@Py2DictObject(op)->ma_table[i]
+ if (@Py2DictEntry(entry_ptr)->me_key == 0
+ || @Py2DictEntry(entry_ptr)->me_value == 0
+ || (! @Py2Int_Check(@Py2DictEntry(entry_ptr)->me_key)
+ && ! @Py2Long_Check(@Py2DictEntry(entry_ptr)->me_key)))
+ continue
+ if ((@Py2Int_Check(@Py2DictEntry(entry_ptr)->me_key)
+ && @Py2Int_AS_LONG(@Py2DictEntry(entry_ptr)->me_key) == key)
+ || (@Py2Long_Check(@Py2DictEntry(entry_ptr)->me_key)
+ && Py2Long_AsLongLong(@Py2DictEntry(entry_ptr)->me_key)
+ == key))
+ return @Py2DictEntry(entry_ptr)->me_value
}
return 0
}
first = 1
for (i = 0; i < n; i++) {
entry_ptr = &@Py2DictObject(object)->ma_table[i]
- if (entry_ptr->me_key == 0 || entry_ptr->me_value == 0)
+ if (@Py2DictEntry(entry_ptr)->me_key == 0
+ || @Py2DictEntry(entry_ptr)->me_value == 0)
continue
if (! first)
retstr .= " "
first = 0
- retstr .= Py2Object_Repr(entry_ptr->me_key)
+ retstr .= Py2Object_Repr(@Py2DictEntry(entry_ptr)->me_key)
retstr .= ":"
- retstr .= Py2Object_Repr(entry_ptr->me_value)
+ retstr .= Py2Object_Repr(@Py2DictEntry(entry_ptr)->me_value)
}
retstr .= "}"
return retstr
@__pointer(object))
}
+# This function isn't really based on a function in object.c, but
+# it is based on Py2Object_Repr().
+private function Py2Object_Repr:string(object:long, index:long)
+{
+ if (object == 0)
+ return "<NULL>"
+ if (@Py2String_Check(object))
+ return sprintf("\"%c\"", stringat(Py2String_AsString(object), index))
+ if (@Py2Tuple_Check(object))
+ return Py2Object_Repr(Py2Tuple_GetItem(object, index))
+ if (@Py2List_Check(object))
+ return Py2Object_Repr(Py2List_GetItem(object, index))
+ if (@Py2Dict_Check(object))
+ return Py2Object_Repr(Py2Dict_GetItem_FromLong(object, index))
+
+ error(sprintf("TypeError: '%s' object cannot be indexed",
+ python2_get_typename(object)))
+ return ""
+}
+
#
# Systemtap support functions for python 2.
#
printf("Traceback (most recent call first):\n")
while (frame != 0) {
lineno = Py2Frame_GetLineNumber(frame)
- code = @Py2FrameObject(frame)->f_code
- filename = Py2String_AsString(code->co_filename)
- name = Py2String_AsString(code->co_name)
+ f_code = @Py2FrameObject(frame)->f_code
+ filename = Py2String_AsString(@Py2CodeObject(f_code)->co_filename)
+ name = Py2String_AsString(@Py2CodeObject(f_code)->co_name)
# Quit when we make it back to the HelperSDT module.
if (isinstr(filename, "/HelperSDT/"))
retstr = "Traceback (most recent call first):\n"
while (frame != 0) {
lineno = Py2Frame_GetLineNumber(frame)
- code = @Py2FrameObject(frame)->f_code
- filename = Py2String_AsString(code->co_filename)
- name = Py2String_AsString(code->co_name)
+ f_code = @Py2FrameObject(frame)->f_code
+ filename = Py2String_AsString(@Py2CodeObject(f_code)->co_filename)
+ name = Py2String_AsString(@Py2CodeObject(f_code)->co_name)
# Quit when we make it back to the HelperSDT module.
if (isinstr(filename, "/HelperSDT/"))
# flags == 2: get all variables
if (flags == 2) {
i = 0
- n = f_code->co_nlocals
+ n = @Py2CodeObject(f_code)->co_nlocals
}
else {
- n = f_code->co_argcount
- if (f_code->co_flags & %{ Py2_CO_VARARGS %})
+ n = @Py2CodeObject(f_code)->co_argcount
+ if (@Py2CodeObject(f_code)->co_flags & %{ Py2_CO_VARARGS %})
n++
- if (f_code->co_flags & %{ Py2_CO_VARKEYWORDS %})
+ if (@Py2CodeObject(f_code)->co_flags & %{ Py2_CO_VARKEYWORDS %})
n++
# flags == 0 (parms only): 0 to n (argcount)
# flags == 1 (locals only): n (argcount) to max
else if (flags == 1) {
i = n
- n = f_code->co_nlocals
+ n = @Py2CodeObject(f_code)->co_nlocals
}
}
if (i < 0 || i > n) {
# Each element in co_varnames is a tuple of strings. The values
# are in f_localsplus.
- p = f_code->co_varnames
+ p = @Py2CodeObject(f_code)->co_varnames
localsplus = @Py2FrameObject(frame)->f_localsplus
first = 1
for (; i < n; i++) {
function python2_get_variable:string(frame:long, var:string)
{
f_code = @Py2FrameObject(frame)->f_code
- n = f_code->co_nlocals
+ n = @Py2CodeObject(f_code)->co_nlocals
# Each element in co_varnames is a tuple of strings. The values
# are in f_localsplus.
- p = f_code->co_varnames
+ p = @Py2CodeObject(f_code)->co_varnames
localsplus = @Py2FrameObject(frame)->f_localsplus
for (i = 0; i < n; i++) {
key_obj = Py2Tuple_GetItem(p, i)
}
return Py2Object_Repr(value)
}
+
+function python2_get_variable:string(frame:long, var:string, index:long)
+{
+ f_code = @Py2FrameObject(frame)->f_code
+ n = @Py2CodeObject(f_code)->co_nlocals
+
+ # Each element in co_varnames is a tuple of strings. The values
+ # are in f_localsplus.
+ p = @Py2CodeObject(f_code)->co_varnames
+ localsplus = @Py2FrameObject(frame)->f_localsplus
+ for (i = 0; i < n; i++) {
+ key_obj = Py2Tuple_GetItem(p, i)
+ if (var == Py2String_AsString(key_obj)) {
+ value_obj = user_long(localsplus + (i * %{ sizeof(intptr_t) %}))
+ return Py2Object_Repr(value_obj, index)
+ }
+ }
+
+ # If we can't find it in the locals, we look in the globals.
+ f_globals = @Py2FrameObject(frame)->f_globals
+ value_obj = Py2Dict_GetItem(f_globals, var)
+ if (value_obj == 0) {
+ error(sprintf("Python variable '%s' cannot be found\n", var))
+ return ""
+ }
+ return Py2Object_Repr(value_obj, index)
+}
return 0
}
+# This function isn't really based on a function in dictobject.c, but
+# it is based on Py3Dict_GetItem().
+private function Py3Dict_GetItem_FromLong:long(op:long, key:long)
+{
+ if (!@Py3Dict_Check(op)) {
+ error(sprintf("Py3Dict_GetItem called on %s object at %p\n",
+ python3_get_typename(op), @__pointer(op)))
+ return 0
+ }
+
+ // See Py3Dict_GetItem() for details on dicts.
+
+ // If we've got a split table...
+ if (@Py3DictObject(op)->ma_values != 0) {
+ n = @Py3DictObject(op)->ma_used
+ for (i = 0; i < n; i++) {
+ entry_ptr = &@DK_ENTRIES(@Py3DictObject(op)->ma_keys)[i]
+ if (entry_ptr->me_key == 0
+ || ! @Py3Long_Check(entry_ptr->me_key))
+ continue
+ if (Py3Long_AsLongLong(entry_ptr->me_key) == key)
+ return @Py3DictObject(op)->ma_values[i]
+ }
+ }
+ // If we've got a combined table...
+ else {
+ n = @choose_defined(@Py3DictObject(op)->ma_keys->dk_nentries,
+ @DK_SIZE(@Py3DictObject(op)->ma_keys))
+ for (i = 0; i < n; i++) {
+ entry_ptr = &@DK_ENTRIES(@Py3DictObject(op)->ma_keys)[i]
+ if (entry_ptr->me_key == 0 || entry_ptr->me_value == 0
+ || ! @Py3Long_Check(entry_ptr->me_key))
+ continue
+ if (Py3Long_AsLongLong(entry_ptr->me_key) == key)
+ return entry_ptr->me_value
+ }
+ }
+ return 0
+}
+
private function Py3Dict_Repr:string(object:long)
{
if (!@Py3Dict_Check(object)) {
@__pointer(object))
}
+# This function isn't really based on a function in object.c, but
+# it is based on Py3Object_Repr().
+private function Py3Object_Repr:string(object:long, index:long)
+{
+ if (object == 0)
+ return "<NULL>"
+ if (@Py3Unicode_Check(object))
+ return sprintf("\"%c\"", stringat(Py3Unicode_AsASCIIString(object),
+ index))
+ if (@Py3Tuple_Check(object))
+ return Py3Object_Repr(Py3Tuple_GetItem(object, index))
+ if (@Py3List_Check(object))
+ return Py3Object_Repr(Py3List_GetItem(object, index))
+ if (@Py3Dict_Check(object))
+ return Py3Object_Repr(Py3Dict_GetItem_FromLong(object, index))
+
+ error(sprintf("TypeError: '%s' object cannot be indexed",
+ python3_get_typename(object)))
+ return ""
+}
+
#
# Systemtap support functions for python 3.
#
}
return Py3Object_Repr(value)
}
+
+function python3_get_variable:string(frame:long, var:string, index:long)
+{
+ f_code = @Py3FrameObject(frame)->f_code
+ n = @Py3CodeObject(f_code)->co_nlocals
+
+ # Each element in co_varnames is a tuple of strings. The values
+ # are in f_localsplus.
+ p = @Py3CodeObject(f_code)->co_varnames
+ localsplus = @Py3FrameObject(frame)->f_localsplus
+ for (i = 0; i < n; i++) {
+ key_obj = Py3Tuple_GetItem(p, i)
+ if (var == Py3Unicode_AsASCIIString(key_obj)) {
+ value_obj = user_long(localsplus + (i * %{ sizeof(intptr_t) %}))
+ return Py3Object_Repr(value_obj, index)
+ }
+ }
+
+ # If we can't find it in the locals, we look in the globals.
+ f_globals = @Py3FrameObject(frame)->f_globals
+ value_obj = Py3Dict_GetItem(f_globals, var)
+ if (value_obj == 0) {
+ error(sprintf("Python variable '%s' cannot be found\n", var))
+ return ""
+ }
+ return Py3Object_Repr(value_obj, index)
+}