Monday, April 25, 2011

GDB Python Script To Get The Start Address Of A Loaded Library


The following GDB Python convenience function (as defined by the script) will search through the output of (gdb) info proc mappings for the library you've specified in the function parameter and return the start address of the .text segment of that library or executable.

Here is an example output of (gdb) info proc mapping with the entry for libc.so highlighted in red.  The Start Addr is what we'll have the convenience function fetch:
   Start Addr        End Addr       Size     Offset objfile
     0x100000        0x103000     0x3000   0x100000
    0x8000000       0x8029000    0x29000          0   /home/user/glibc64_power6/elf/ld.so
    0x8039000       0x803a000     0x1000    0x29000   /home/user/glibc64_power6/elf/ld.so
    0x803a000       0x803e000     0x4000    0x2a000   /home/user/glibc64_power6/elf/ld.so
   0x10000000      0x10002000     0x2000          0   /home/user/libdfp64_power6/test-isinf
   0x10011000      0x10012000     0x1000     0x1000   /home/user/libdfp64_power6/test-isinf
0x40000000000   0x40000002000     0x2000          0
0x40000002000   0x40000195000   0x193000          0   /home/user/glibc64_power6/libc.so
0x40000195000   0x400001a4000     0xf000   0x193000   /home/user/glibc64_power6/libc.so
0x400001a4000   0x400001a8000     0x4000   0x192000   /home/user/glibc64_power6/libc.so
0x400001a8000   0x400001bf000    0x17000   0x196000   /home/user/glibc64_power6/libc.so
0x400001bf000   0x400001c3000     0x4000   0x1bf000
0x400001c3000   0x4000026b000    0xa8000          0   /home/user/glibc64_power6/math/libm.so
0x4000026b000   0x4000027a000     0xf000    0xa8000   /home/user/glibc64_power6/math/libm.so
0x4000027a000   0x4000027b000     0x1000    0xa7000   /home/user/glibc64_power6/math/libm.so
0x4000027b000   0x40000285000     0xa000    0xa8000   /home/user/glibc64_power6/math/libm.so
0x40000285000   0x40000286000     0x1000   0x285000
0x40000286000   0x400002a3000    0x1d000          0   /home/user/glibc64_power6/nptl/libpthread.so
0x400002a3000   0x400002b2000     0xf000    0x1d000   /home/user/glibc64_power6/nptl/libpthread.so
0x400002b2000   0x400002b3000     0x1000    0x1c000   /home/user/glibc64_power6/nptl/libpthread.so
0x400002b3000   0x400002b5000     0x2000    0x1d000   /home/user/glibc64_power6/nptl/libpthread.so
0x400002b5000   0x400002ba000     0x5000   0x2b5000
0x400002ba000   0x4000031a000    0x60000          0   /home/user/libdfp64_power6/libdfp-1.0.7.so
0x4000031a000   0x40000329000     0xf000    0x60000   /home/user/libdfp64_power6/libdfp-1.0.7.so
0x40000329000   0x40000332000     0x9000    0x5f000   /home/user/libdfp64_power6/libdfp-1.0.7.so
0x40000332000   0x40000334000     0x2000   0x332000
0xffffff9d000   0xffffffb3000    0x16000 0xfff9d000               [stack]

Add the following to your ~.gdbinit file, or source it directly in your .gdb script:
source /path/to/gdb_start_address.py
gdb_start_address.py:
# gdb_start_address.py created by Ryan S. Arnold, April 2011.  No
# attribution required or necessary to use/reuse/copy/modify this
# function/script.

import re
class StartAddress(gdb.Function):
    """Returns the start address of a library or executable from info
    proc mappings."""

    def __init__(self):
        super (StartAddress, self).__init__ ("start_address")

    def invoke(self, library):
        mappings = gdb.execute("info proc mappings", to_string=True)
        lines = mappings.split('\n')
        to_mappings = ""
        for line in lines:
            if (to_mappings != "true"):
                if (re.search("Start Addr", line)):
                    to_mappings = "true"
                continue
            else:

                # The first match is the .text segment. Make sure to
                # match on "/libdfp-1.0.7.so" when passed "libdfp" and
                # not on "/libdfp" in the following example:
                # /home/ryanarn/libdfp/build64_power6/libdfp-1.0.7.so
                if (re.search("/" + library.string() + "[^/]*$", line)):
                    chunks = line.split()
                    return int(str(chunks[0]),16)
        return 0x0

StartAddress ()
There is currently a bug in GDB which crashes GDB after a direct assignment from this user function, e.g., (gdb) set $foo = $start_address("libc"). To use the function to set a variable do the following:
(gdb) p $start_address("libc")
$3 = 4398046760960
(gdb) set $foo = $
(gdb) p $foo
$4 = 4398046760960
I created this function to use in the Libdfp Makefile.gdb GNU make script.  Libdfp's Make system will automatically generate .gdb scripts for each of the test cases in the test-suite.  I use this function to find the load address of the library so that I can programmaticaly load the symbol file in the correct location, as in the following snippet of test-isinf.gdb:
source /home/ryanarn/eglibc/eglibc/libdfp/trunk/tests/gdb_start_address.py
...
p/x $start_address("libdfp")
set $libdfp_start = $
set $libdfp_text = 0x0af40
set $libdfp_addr = $libdfp_start + $libdfp_text
add-symbol-file ./libdfp.so.1 $libdfp_addr

Power.org Published the Power Architecture 32-bit ELF ABI Supplement

Power.org has published the Power Architecture® 32-bit Application Binary Interface Supplement 1.0 - Linux® & Embedded.
http://www.power.org/resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Unified.pdf
This is a specification document that I worked on for four years as part of the PowerABI TSC, under Power.org.

It defines the 32-bit Power Architecture processor specific ELF ABI for the GNU/Linux Operating System and Embedded environments.

I served as the document owner, style-sheet maintainer, and TSC Chair (for the last year).  It's very rewarding (relieving) to see this finally published.  It was a pleasure to work with everyone on the TSC.  Their expertise and contributions were invaluable.


There are three versions of the document: the Linux & Embedded (Unified), the Linux, and the Embedded.  These are all generated from the same parent document and are separated for convenience of the readers.

http://www.power.org/resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Unified.pdf
http://www.power.org/resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Linux.pdf
http://www.power.org/resources/downloads/Power-Arch-32-bit-ABI-supp-1.0-Embedded.pdf

Sunday, April 24, 2011

Embedding SVG images that use Javascript in Blogger/Blogspot Posts

In Blogger posts if you want to embed SVG images that make use of JavaScript (for animation control) you need to use the html <embed> tag since <object> and <img> don't allow scripting. You'll have to edit the HTML directly to use the <embed> tag as in the following example:
<embed src="http://rsasandbox.appspot.com/embed.svg" type="image/svg+xml" width="230" height="230"/>
The following embedded SVG example uses the <animateMotion> SVG element with repeatCount="indefinite" so that the animation continues indefinitely.  The animation is paused and restarted by calling JavaScript functions as a result of SVG element onclick event processing, e.g., onclick='Pause(evt)' and onclick='Play(evt)'.

http://rsasandbox.appspot.com/embed.svg

Saturday, April 23, 2011

SVG Animation and The SVG DOM beginElement() Method

This example attempts to restart the animation using the SVG DOM beginElement() method. It keeps the bubble going back and forth along a zig-zag path.  It restarts the animation once the bubble has returned to the start position by using beginElement ( ) upon the original <animateMotion>.  The following SVG code is just the XML necessary to show the beginElement ( ) method call.

http://rsasandbox.appspot.com/beginElement-ex.svg










Note: If the example animation does not restart after one complete circuit it means that your browser (like Chrome) doesn't yet support the SVG DOM beginElement ( ) method.  The animation should restart properly in the Opera browser.
<script type="text/javascript" >
<![CDATA[
      function BeginAgain(bubble) {
          var bub = SVGDocument.getElementById(bubble);
          bub.beginElement();
      }
]]>
</script>
...
<animateMotion  id="bubble1am1" ...  >
...
<animateMotion  id="bubble2am1"
     begin="bubble1am1.end"
     ...
     onend="BeginAgain('bubble1am1')" >

SVG <animateMotion> "fill" Attribute Conformance

I've been tinkering with SVG AnimateMotion fill attribute conformance in various HTML5 capable browsers to try to figure out what is supposed to be the normative behavior.

The SVG Animation specification for the "fill" attribute indicates that the possible values for the attribute are fill = "freeze" | "remove".

freeze

The animation effect F(t) is defined to freeze the effect value at the last value of the active duration. The animation effect is "frozen" for the remainder of the document duration (or until the animation is restarted
remove

The animation effect is removed (no longer applied) when the active duration of the animation is over. After the active end of the animation, the animation no longer affects the target (unless the animation is restarted.
The specification defines fill="remove" as the default.

The following SVG Animation fragment demonstrates the use of "fill".

<use xlink:href="#engine_v2"
  id="engine1"
  visibility="visible"
  centered="no"
  x="-19.5"
  y="-7.5">
        <animateMotion
          id="engine1am1"
          dur="4s"
          keyPoints=".07; .92"
          keyTimes="0; 1"
          rotate="auto"
          repeatCount="1"
          calcMode="linear"
          restart="whenNotActive"
          fill="freeze" >
                <mpath xlink:href="#simple-track-path1" />
        </animateMotion>
        <animateMotion
          id="engine1am2"
          begin="engine1am1.end"
          dur="4s"
          keyPoints=".92; .07"
          keyTimes="0; 1"
          rotate="auto"
          repeatCount="1"
          calcMode="linear"
          restart="always"
          fill="freeze" >
                <mpath xlink:href="#simple-track-path1" />
        </animateMotion>
</use>

The following live SVG Animation example demonstrates the use of fill="none" (i.e., the default), fill="freeze", and fill="remove". In the animation a train car travels a path in one direction and then travels the path in the reverse direction using two consecutive AnimateMotion elements.


http://rsasandbox.appspot.com/anim6.svg
Note: You will only see this SVG image animated if your browser supports SVG Animation, even then your mileage may vary as the animation may have run and completed before it displays.  Click on the image to view it








The fill attribute for the first AnimateMotion element doesn't seem to matter when there are two consecutive AnimateMotion elements.  Only the second fill attribute matters and it determines the image state following the completion of the animation.

The Chrome browser, as of version 11.0.696.16 beta, finishes the animation in the following way:
Screenshot of Chrome

The Opera browser, as of version 11.01, finishes the animation in the following way:
Screenshot of Opera
Based on the reading of the specification I believe that Opera is performing correctly in this instance.

Unfortunately the behavior of the fill attribute changes when there aren't two consecutive elements of the same type.  The following example shows an animateTransform following an animateMotion as demonstrated by the following SVG example:

http://rsasandbox.appspot.com/anim7.svg

In this example the train car is supposed to travel along the path, turns around 180 degrees, and then travel back along the path.
This example only works under the Opera browser where the fill attribute is used with the animateTransform element, e.g., <animateTransform fill="freeze">.  This seems to be the correct behavior.  When fill="remove" the orientation of the train car returns to the original orientation, i.e., not rotated, after the animateTransform element rotates it.  With fill="freeze" the train car retains the rotate orientation.
Screenshot of Opera
Under the Chrome browser the train disappears following the <animateTransform fill="freeze"> element.  I believe this is a bug in the Chrome browser.  It seems to behave as expected in the <animateTransform fill="remove"> example.
Screenshot of Chrome






Using Google's App Engine to serve SVG files

I've been tinkering with SVG Animation support in HTML5 lately and since I don't like to maintain web servers myself I needed somewhere convenient to host my Javascript and SVG creations. My friend Jeff Bailey suggested that I check out Google's App Engine.

While App Engine may be a bit overkill for serving static content, recent additions to SVG allow animation elements. What appears to be a static SVG file may in-fact have embedded Javascript and SVG Animation elements.

App Engine has proven to be a great environment to work with but in order for it to properly serve SVG files such that a browser can display the images rather than the XML data the server needs to export the proper MIME type information for SVG files. This is accomplished by telling the App Engine server how to serve the SVG files.

App Engine supports both Java and Python servers. I use the Python server and the server configuration files are in YAML. The following YAML fragment is added to the project's app.yaml configuration file to support SVG MIME types:
handlers:
- url: /(.*\.svg)
static_files: static/\1
upload: static/(.*\.svg)
mime_type: image/svg+xml

The following is a little tech demo I've made using App Engine:











Note: SVG Animation support is still in development by most browsers. The ones I've tested are Chrome, Opera, and Firefox. The level of conformance for each of these browsers vary. This demo works best on Chrome 11.0.696.16 beta. The spacing of the train-cars is a little off in Opera. I'm not sure which browser is the most spec conformant.

The following app.yaml file is complete example that is used for the rsasandbox project:
application: rsasandbox
version: 1
runtime: python
api_version: 1

handlers:
- url: /(.*\.(html|png|jpg|gif))
static_files: static/\1
upload: static/(.*\.(html|gif|png|jpg))

- url: /(.*\.svg)
static_files: static/\1
upload: static/(.*\.svg)
mime_type: image/svg+xml

- url: /(.*\.xml)
static_files: static/\1
upload: static/(.*\.xml)