{"id":636,"date":"2010-11-24T16:35:13","date_gmt":"2010-11-24T06:35:13","guid":{"rendered":"http:\/\/brnz.org\/hbr\/?p=636"},"modified":"2010-11-23T21:17:11","modified_gmt":"2010-11-23T11:17:11","slug":"assembly-primer-part-4-hello-world-spu","status":"publish","type":"post","link":"https:\/\/brnz.org\/hbr\/?p=636","title":{"rendered":"Assembly Primer Part 4 &#8212; Hello World &#8212; SPU"},"content":{"rendered":"<p>These are my notes for where I can see SPU varying from ia32, as presented in the video\u00a0<a href=\"http:\/\/www.securitytube.net\/Assembly-Primer-for-Hackers-(Part-4)-Hello-World-video.aspx\">Part 4 \u2014 Hello World<\/a>.<\/p>\n<h2><span style=\"font-weight: normal; font-size: 13px;\">I&#8217;ve written about syscalls on SPU before,\u00a0<a href=\"https:\/\/brnz.org\/hbr\/?p=521\">here<\/a>. \u00a0System calls can be performed using appropriately packed data and\u00a0stopcode 0x2104, which is intercepted by the kernel.<\/span><\/h2>\n<p>The <a href=\"http:\/\/code.securitytube.net\/JustExit.s\">JustExit.s<\/a> example in the video uses the exit syscall, which is <a href=\"http:\/\/git.kernel.org\/?p=linux\/kernel\/git\/torvalds\/linux-2.6.git;a=blob;f=arch\/powerpc\/platforms\/cell\/spu_callbacks.c;h=fec1495e6b12f98a8a12e9c9436fa2f2fdc76782;hb=HEAD#l16\">explicitly excluded<\/a> from being called by the SPU. \u00a0For the sake of the example, we can use the time syscall instead, and so a simple syscall looks something like this:<\/p>\n<pre style=\"padding-left: 30px;\">.data\r\nsyscall_time:\r\n    .quad 13 # syscall number and return value\r\n    .quad 0  # parameters\r\n    .quad 0\r\n    .quad 0\r\n    .quad 0\r\n    .quad 0\r\n    .quad 0\r\n\r\n.text\r\n.globl _start\r\n_start:\r\n    stop 0x2104\r\n    .int syscall_time<\/pre>\n<p>syscall_time is the structure used by the syscall (see <a href=\"http:\/\/sourceware.org\/cgi-bin\/cvsweb.cgi\/src\/newlib\/libc\/machine\/spu\/sys\/linux_syscalls.h?rev=1.3&amp;content-type=text\/x-cvsweb-markup&amp;cvsroot=src\">struct spu_syscall_block<\/a> and <a href=\"http:\/\/sourceware.org\/cgi-bin\/cvsweb.cgi\/src\/libgloss\/spu\/linux_syscalls.c?rev=1.2&amp;content-type=text\/x-cvsweb-markup&amp;cvsroot=src\">__linux_syscall()<\/a>) with 13 in the first unsigned long long. (&#8220;Obviously&#8221;, .quad is 8 bytes :\\). \u00a0If there were arguments to pass to the syscall, they would be placed in the six following .quads.<\/p>\n<p>The address of the syscall block must follow directly after the stop instruction. \u00a0(I did wonder if there would be some trick to mixing the address with the program code &#8212; as you can see, no trick needed)<\/p>\n<p>The syscall&#8217;s return value is placed in the first 8 bytes of the syscall block.<\/p>\n<p>While it&#8217;s possible to use the write syscall, it&#8217;s rather painful as it requires a valid char* ea to be passed to be written, which is not readily accessible from the SPU. \u00a0The alternative is to use the <a href=\"http:\/\/sourceware.org\/cgi-bin\/cvsweb.cgi\/src\/libgloss\/spu\/syscalls.c?rev=1.9&amp;content-type=text\/x-cvsweb-markup&amp;cvsroot=src\">__send_to_ppe()<\/a> function &#8212; <a href=\"http:\/\/sourceware.org\/cgi-bin\/cvsweb.cgi\/src\/libgloss\/spu\/write.c?rev=1.5&amp;content-type=text\/x-cvsweb-markup&amp;cvsroot=src\">write()<\/a> is one of the POSIX1 functions handled by newlib+libspe. \u00a0Of course, it has a slightly different calling mechanism to to __linux_syscall(), uses the JSRE_POSIX1 stopcode of 0x2101. \u00a0This works:<\/p>\n<pre style=\"padding-left: 30px;\">.data\r\n\r\nHelloWorldString:\r\n    .ascii \"Hello world\\n\"\r\n\r\nsend_to_ppe_write:\r\n    .int 1 # stdout\r\n    .int 0 # pad\r\n    .int 0 # pad\r\n    .int 0 # pad\r\n    .int HelloWorldString # char* in local store\r\n    .int 0 # pad\r\n    .int 0 # pad\r\n    .int 0 # pad\r\n    .int 12 # length\r\n    .int 0 # pad\r\n    .int 0 # pad\r\n    .int 0 # pad\r\n\r\n.text\r\n.globl _start\r\n\r\n_start:\r\n    stop 0x2101\r\n    .int send_to_ppe_write+0x1b000000<\/pre>\n<p>Although I&#8217;m sure it can be expressed more elegantly.<\/p>\n<p>The magic number 0x1b000000 added to the address of send_to_ppe_write is derived from the &#8220;combined&#8221; variable from\u00a0<a href=\"http:\/\/sourceware.org\/cgi-bin\/cvsweb.cgi\/src\/libgloss\/spu\/syscalls.c?rev=1.9&amp;content-type=text\/x-cvsweb-markup&amp;cvsroot=src\">__send_to_ppe()<\/a> with the values from <a href=\"http:\/\/sourceware.org\/cgi-bin\/cvsweb.cgi\/src\/libgloss\/spu\/jsre.h?rev=1.22&amp;content-type=text\/x-cvsweb-markup&amp;cvsroot=src\">jsre.h<\/a>.<\/p>\n<h2>Alternatively&#8230;<\/h2>\n<p>I just realised that this works: if \/proc\/sys\/kernel\/randomize_va_space is zero, the address of the mapped SPU LS (from \/proc\/$PID\/maps, as seen <a href=\"https:\/\/brnz.org\/hbr\/?p=633\">here<\/a>) of 0xf7f70000 can be used as an offset to anything in local store, so the syscall will work with offset pointers:<\/p>\n<pre style=\"padding-left: 30px;\">.data\r\n\r\nHelloWorldString:\r\n    .ascii \"Hello World\\n\"\r\n\r\nsyscall_write:\r\n    .quad 4 # write\r\n    .quad 1 # stdout\r\n    .int  0 # gas doesn't seem to like doing the arithmetic in a .quad\r\n    .int 0xf7f70000 + HelloWorldString # mapped address of string\r\n    .quad 12 # length\r\n    .quad 0\r\n    .quad 0\r\n    .quad 0\r\n\r\n.text\r\n\r\n.globl _start\r\n\r\n_start:\r\n    stop 0x2104\r\n    .int syscall_write<\/pre>\n<p>Hideous :)<\/p>\n<h3>Previous assembly primer notes\u2026<\/h3>\n<p>Part 1 \u2014 System Organization \u2014\u00a0<a href=\"https:\/\/brnz.org\/hbr\/?p=631\">PPC<\/a> \u2014\u00a0<a href=\"https:\/\/brnz.org\/hbr\/?p=632\">SPU<\/a><br \/>\nPart 2 \u2014 Memory Organisation \u2014\u00a0<a href=\"https:\/\/brnz.org\/hbr\/?p=633\">SPU<\/a><br \/>\nPart 3 &#8212; GDB Usage Primer &#8212;\u00a0<a href=\"https:\/\/brnz.org\/hbr\/?p=634\">PPC &amp; SPU<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>These are my notes for where I can see SPU varying from ia32, as presented in the video\u00a0Part 4 \u2014 Hello World. I&#8217;ve written about syscalls on SPU before,\u00a0here. \u00a0System calls can be performed using appropriately packed data and\u00a0stopcode 0x2104, which is intercepted by the kernel. The JustExit.s example in the video uses the exit &hellip; <a href=\"https:\/\/brnz.org\/hbr\/?p=636\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;Assembly Primer Part 4 &#8212; Hello World &#8212; SPU&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[5,26],"tags":[38,40],"_links":{"self":[{"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/posts\/636"}],"collection":[{"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=636"}],"version-history":[{"count":7,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/posts\/636\/revisions"}],"predecessor-version":[{"id":696,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=\/wp\/v2\/posts\/636\/revisions\/696"}],"wp:attachment":[{"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=636"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=636"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/brnz.org\/hbr\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=636"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}