<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:admin="http://webns.net/mvcb/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:creativeCommons="http://backend.userland.com/creativeCommonsRssModule" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:html="http://www.w3.org/1999/html" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><title>technovelty</title><link>http://www.technovelty.org</link><description>From the keyboard of Ian Wienand</description><language>en</language><ttl>60</ttl><dc:creator>Ian Wienand</dc:creator><admin:generatorAgent rdf:resource="http://roughingit.subtlehints.net/pyblosxom" /><admin:errorReportsTo rdf:resource="mailto:ianw@ieee.org" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/technovelty" /><feedburner:info uri="technovelty" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><creativeCommons:license>http://creativecommons.org/licenses/by-sa/3.0/</creativeCommons:license><feedburner:browserFriendly>This is an XML content feed. It is intended to be viewed in a newsreader or syndicated to another site, subject to copyright and fair use.</feedburner:browserFriendly><item><title>Separate debug info</title><guid isPermaLink="false">code/debug-info.html</guid><link>http://www.technovelty.org/code/debug-info.html</link><description>I've recently found out a bit more about separating debug info, and thought a consolidated reference might be handy. The ...</description><content:encoded><![CDATA[
<p>I've recently found out a bit more about separating debug info, and
thought a consolidated reference might be handy.</p>

<h4>The Idea</h4>

<p>Most every distribution now provides separate debug packages which
contain only the debug info, saving much space for the 99% of people
who never want to start gdb.</p>

<p>This is achieved with <tt>objcopy</tt> and
<tt>--only-keep-debug</tt>/<tt>--add-gnu-debuglink</tt> and is well
explained in the <a
href="http://sourceware.org/binutils/docs/binutils/objcopy.html">man
page</a>.</p>

<h4>What does this do?</h4>

<p>This adds a <tt>.gnu_debuglink</tt> section to the binary with the
name of debug file to look for.</p>

<div class="codebox">
<pre>
$ gcc -g -shared -o libtest.so libtest.c
$ objcopy --only-keep-debug libtest.so libtest.debug
$ objcopy --add-gnu-debuglink=libtest.debug libtest.so
$ objdump -s -j .gnu_debuglink libtest.so

libtest.so:     file format elf32-i386

Contents of section .gnu_debuglink:
 0000 6c696274 6573742e 64656275 67000000  libtest.debug...
 0010 52a7fd0a                             R... 
</pre>
</div>

<p>The first part is the name of the file, the second part is a
check-sum of debug-info file for later reference.</p>

<h4>Build ID</h4>

<p>Did you know that binaries also get stamped with a unique id when
they are built?  The <tt>ld</tt> <tt>--build-id</tt> flag stamps in a
hash near the end of the link.</p>

<div class="codebox">
<pre>
$ readelf --wide --sections ./libtest.so  | grep build
  [ 1] .note.gnu.build-id NOTE            000000d4 0000d4 000024 00   A  0   0  4
$ objdump -s -j .note.gnu.build-id libtest.so 

libtest.so:     file format elf32-i386

Contents of section .note.gnu.build-id:
 00d4 04000000 14000000 03000000 474e5500  ............GNU.
 00e4 a07ab0e4 7cd54f60 0f5cf66b 5799b05c  .z..|.O`.\.kW..\
 00f4 2d43f456                             -C.V            
</pre>
</div>

<p>Incase you're wondering what the format of that is...</p>

<div class="codebox">
<pre>
uint32 name_size; /* size of the name */
uint32 hash_size; /* size of the hash */
uint32 identifier; /* NT_GNU_BUILD_ID == 0x3 */
char   name[name_size]; /* the name "GNU" */
char   hash[hash_size]; /* the hash */
</pre>
</div>

<p>Although the actual file may change (due to prelink or similar) the
hash will not be updated and remain constant.</p>

<h4>Finding the debug info files</h4>

<p>The last piece of the puzzle is how gdb attempts to find the
debug-info files when it is run.  The main variable influencing this
is <tt>debug-file-directory</tt>.</p>

<div class="codebox">
<pre>
(gdb) show debug-file-directory 
The directory where separate debug symbols are searched for is "/usr/lib/debug".
</pre>
</div>

<p>The first thing gdb does, which you can verify via an strace, is
search for a file called
<tt>[debug-file-directory]/.build-id/xx/yyyyyy.debug</tt>; where xx is
the first two hexadecimal digits of the hash, and yyy the rest of
it:</p>

<div class="codebox">
<pre>
$ objdump -s -j .note.gnu.build-id /bin/ls

/bin/ls:     file format elf32-i386

Contents of section .note.gnu.build-id:
 8048168 04000000 14000000 03000000 474e5500  ............GNU.
 8048178 c6fd8024 2a11673c 7c6a5af6 2c65b1b5  ...$*.g&lt;|jZ.,e..
 8048188 d7e13fd4                             ..?.            

... [running gdb /bin/ls] ...

access("/usr/lib/debug/.build-id/c6/fd80242a11673c7c6a5af62c65b1b5d7e13fd4.debug", F_OK) = -1 ENOENT (No such file or directory)
</pre>
</div>

<p>Next it moves onto the debug-link info filename.  First it looks
for the filename in same directory as the object being debugged.
After that it looks for the file in a sub-directory called
<tt>.debug/</tt> in the same directory.</p>

<p>Finally, it prepends the <tt>debug-file-directory</tt> to the path
of the object being inspected and looks for the debug info there.
This is why the </tt>/usr/lib/debug</tt> directory looks like the root
of a file-system; if you're looking for the debug-info of
<tt>/usr/lib/libfoo.so</tt> it will be looked for in
<tt>/usr/lib/debug/usr/lib/libfoo.so</tt>.</p>

<p>Interestingly, the <tt>sysroot</tt> and <tt>solib-search-path</tt>
don't appear to have anything to do with these lookups.  So if you
change the sysroot, you also need to change the
<tt>debug-file-directory</tt> to match.</p>

<p>However, most distributions make all this "just work", so hopefully
you'll never have to worry about anyway!</p>
]]></content:encoded><category domain="http://www.technovelty.org">code</category><dc:date>2010-01-21T22:11:00Z</dc:date></item><item><title>Salton (Sim)City</title><guid isPermaLink="false">humor/salton-simcity.html</guid><link>http://www.technovelty.org/humor/salton-simcity.html</link><description>I was recently driving through the California desert and came across the Salton Sea . Long story short - it ...</description><content:encoded><![CDATA[
<p>I was recently driving through the California desert and came
across the <a href="http://en.wikipedia.org/wiki/Salton_Sea">Salton
Sea</a>.  Long story short - it rained a lot and the Colorado River
overflowed a bunch of dams and dikes meant to contain it and created a
huge inland sea.  Oops.</p>

<p>Some enterprising souls must have decided that despite the lack of
any natural flushing dooming the sea to a salty, polluted existence,
there was ripe opportunity to create a sea-side metropolis.</p>

<p>From the ground, it is a bit of a fun ghost town to explore.  The
typical "everything just abandoned" type thing.  But when I came to
geotag some photos I took there, I was quite astonished to see <a
href="http://maps.google.com/maps?q=salton+city&ei=EftLS5-OKI62swOLlrCfCw&ved=0CFYQ_AUoAw&ie=UTF8&hq=&hnear=Salton+City,+Imperial,+California&ll=33.29865,-115.956111&spn=0.033215,0.077162&t=h&z=14">this</a>.</p>

<img src="http://www.technovelty.org/images/salton-simcity.jpg"
alt="Salton (Sim)City" />

<p>That looks <b>exactly</b> like what I used to do in SimCity.  I'd
use the F-U-N-D-S cheat at the start to max out my money, then build
my little empire with neat roads and school and harbours and whatnot
&mdash; they've even got an airport! Then I'd press "go" and people
would slowly move in to the residential areas, one house on one block
at a time.</p>

<p>I guess poor old Salton City never made it past "turtle speed"!</p>

]]></content:encoded><category domain="http://www.technovelty.org">humor</category><dc:date>2010-01-11T05:26:00Z</dc:date></item><item><title>vi backup files considered harmful</title><guid isPermaLink="false">linux/tips/vi-backup.html</guid><link>http://www.technovelty.org/linux/tips/vi-backup.html</link><description>Mark this one down as another in the long list of "duh" once you realise what is going on! Bug ...</description><content:encoded><![CDATA[
<p>Mark this one down as another in the long list of "duh" &mdash;
once you realise what is going on!</p>

<p>Bug report comes in about a long running daemon that has stopped
logging.  <tt>lsof</tt> reports the log file is now named
<tt>logfile~</tt> and further more is deleted!  This happens after a
system upgrade scenario, so of course I go off digging through a
multitude of scripts and what-not to find the culprit...</p>

<p>Have you got it yet?</p>

<p>Try this...</p>

<div class="codebox">
<pre>
# lsof | grep syslogd | grep messages
syslogd    1376        root   15w      REG        3,1    99851    4605625 /var/log/messages
</pre>
</div>

<div class="codebox">
<pre>
# cd /var/log/
# vi messages (and save the file)
</pre>
</div>

<div class="codebox">
<pre>
root@jj:/var/log# lsof | grep syslogd | grep messages
syslogd    1376        root   15w      REG        3,1    99851    4605625 /var/log/messages~ (deleted)
</pre>
</div>

<p><tt>vi</tt> is very careful and renames your existing file, so that
if anything goes wrong when writing the new version you can get
something back.  It's a shame the daemon doesn't know about this!  The
kernel is happy to deal with the <tt>rename</tt>, but when the backup
file is <tt>unlink</tt>ed you're out of luck.  Confusingly to a casual
inspection your log file looks like it's there ... just that nothing
is going into it.  (oh, and if you tried that, you might like to
restart <tt>syslogd</tt> now :)</p>

<p>Moral of the story -- overcome that finger-memory and never use
<tt>vi</tt> on a live file; you're asking for trouble!</p>
]]></content:encoded><category domain="http://www.technovelty.org">linux/tips</category><dc:date>2010-01-08T05:15:00Z</dc:date></item><item><title>Stripping shared libraries</title><guid isPermaLink="false">linux/strip.html</guid><link>http://www.technovelty.org/linux/strip.html</link><description>So, how to strip a shared library? --strip-unneeded states that it removes all symbols that are not needed for relocation ...</description><content:encoded><![CDATA[
<p>So, how to strip a shared library?</p>

<p><tt>--strip-unneeded</tt> states that it removes all symbols that
are not needed for relocation processing.  This is a little cryptic,
because one might reasonably assume that a shared library can be
"relocated", in that it can be loaded anywhere.  However, what this
really refers to is object files that are usually built and bundled
into a <tt>.a</tt> archive for static linking.  For an object in an
static library archive to still be useful, global symbols must be
kept, although static symbols can be removed.  Take the following
small example:</p>

<div class="codebox">
<pre>
$ cat libtest.c
static int static_var = 100;
int global_var = 100;

static int static_function(void) {
       return static_var;
}

int global_function(int i) {
    return static_function() + global_var + i;
}
</pre>
</div>

<p>Before stripping:</p>

<div class="codebox">
<pre>
$ gcc -c -fPIC -o libtest.o libtest.c
$ readelf --symbols ./libtest.o

Symbol table '.symtab' contains 18 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
...
     5: 00000000     4 OBJECT  LOCAL  DEFAULT    5 static_var
     6: 00000000    22 FUNC    LOCAL  DEFAULT    3 static_function
    13: 00000004     4 OBJECT  GLOBAL DEFAULT    5 global_var
    16: 00000016    36 FUNC    GLOBAL DEFAULT    3 global_function
</pre>
</div>

<p>After stripping:</p>

<div class="codebox">
<pre>
$ strip --strip-unneeded libtest.o
$ readelf --symbols ./libtest.o 

Symbol table '.symtab' contains 15 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
...
    10: 00000004     4 OBJECT  GLOBAL DEFAULT    5 global_var
    13: 00000016    36 FUNC    GLOBAL DEFAULT    3 global_function
</pre>
</div>

<p>If you <tt>--strip-all</tt> from this object file, it will remove
the entire <tt>.symtab</tt> section and will be useless for further
linking, because you'll never be able to find <tt>global_function</tt>
to call it!.</p>

<p>Shared libraries are different, however.  Shared libraries keep
global symbols in a separate ELF section called <tt>.dynsym</tt>.
<tt>--strip-all</tt> will not touch the dynamic symbol entires, and
thus it is therefore safe to remove all the "standard" symbols from
the output file, without affecting the usability of the shared
library.  For example, <tt>readelf</tt> will still show the
<tt>.dynsym</tt> symbols even after stripping:</p>

<div class="codebox">
<pre>
$ gcc -shared -fPIC -o libtest.so libtest.c
$ strip --strip-all ./libtest.so 
$ readelf  --syms ./libtest.so 

Symbol table '.dynsym' contains 11 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
...
     6: 00000452    36 FUNC    GLOBAL DEFAULT   12 global_function
    10: 000015e0     4 OBJECT  GLOBAL DEFAULT   21 global_var
</pre>
</div>

<p>However, <tt>--strip-unneeded</tt> is smart enough to realise that
a shared-object library doesn't need the <tt>.symtab</tt> section as
well and remove it.</p>

<p>So, conclusions?  <tt>--strip-all</tt> is safe on shared libraries,
because global symbols remain in a separate section, but not on
objects for inclusion in static libraries (relocatable objects).
<tt>--strip-unneeded</tt> is safe for both, and automatically
understands shared objects do not need any <tt>.symtab</tt> entries to
function and removes them; effectively doing the same work as
<tt>--strip-all</tt>.  So, <tt>--strip-unneeded</tt> is essentially
the only tool you need for standard stripping needs!</p>

<p>See also</p>
<ul><li><a
href="http://www.debian.org/doc/debian-policy/ch-files.html">Debian
Policy Manual</a></li>
</ul>
]]></content:encoded><category domain="http://www.technovelty.org">linux</category><dc:date>2009-12-23T05:39:00Z</dc:date></item><item><title>An open letter to Harvey Norman, Norwest, Castle Hill</title><guid isPermaLink="false">general/hdmi-cables.html</guid><link>http://www.technovelty.org/general/hdmi-cables.html</link><description>I usually find blog rants useless, but sometimes something is just so annoying one is sufficiently inspired. Today I went ...</description><content:encoded><![CDATA[
<p>I usually find blog rants useless, but sometimes something is just
so annoying one is sufficiently inspired.  Today I went with my
parents to buy them a Tivo at Harvey Norman, Norwest, Castle Hill,
NSW, Australia.  I am a big Tivo fan; the interface is good and it
"just works".  I don't mind paying for (or in this recommending paying
for) good products.</p>

<p>After selecting the Tivo model, I asked for a HDMI cable.  The
salesman made a series of questions about what sort of HD TV it was
being plugged into; I quickly sensed this as a probe to see what sort
of suckers we were, and requested just a "normal" cable.</p>

<p>At this point, he insisted on a <b>$130</b> (you guessed it)
Monster cable, and had the audacity to say that we didn't need one of
the <i>really</i> expensive cables because our TV wasn't good enough!
I openly expressed my concern, but the annoying high-pressure sales
pitch had just begun.  The amount of, frankly, crap that he spewed
about 4-bit this, 10-bit that, legislating of labels, DA signal
levels, mythical customers who regretted buying the cheap cables and
who knows what else was to the point of being comical if it weren't so
insistent and said with such seeming authority.</p>

<p>There is only one thing that matters - if the cable has passed the
functional requirements for being certified to have the distinctive
HDMI logo plastered on it.  From the <a
href="http://www.hdmi.org/learningcenter/faq.aspx">HDMI FAQ</a>:</p>

<blockquote>
<p>Q. What testing is required?</p>
<p>Prior to mass producing or distributing any Licensed Product or
component that claims compliance with the HDMI Specification (or
allowing someone else to do such activities), each Adopter must test a
representative sample for HDMI compliance. First, the Adopter must
self test as specified in the then-current HDMI Compliance Test
Specification. The HDMI Compliance Test Specification provides a suite
of testing procedures, and establishes certain minimum requirements
specifying how each HDMI Adopter should test Licensed Products for
conformance to the HDMI Specification.</p>
</blockquote>

<p>Now, I can understand that if you buy any old HDMI cable off Ebay
for $1, it may be a knock-off that uses the HDMI logo illegally.  But
there is no way that the certified $50 Philips cable (still very
over-priced, but at least not insane, and discounted to $35) performs
any differently to some overpriced Monster model certified to exactly
the same standard.</p>

<p>The thing that annoyed me most was his analogy to buying a tyre.
He stated that "if you walked up to a tyre salesman and I said don't
want the Pirelli's, just put the cheap-o tires on my Ferrari" I'd be
insane, and thus by extension of that logic I was insane for not
buying a Monster cable for my great new Tivo.</p>

<p>This analogy is completely flawed and really just dishonest.  A
Ferrari is much more powerful and goes much faster than a standard
car.  It is plausible it needs a better engineered tyre to perform
adequately given the additional stresses it undergoes.  A Tivo doesn't
put out any more or any less bits than any other HDMI certified
equipment, no matter what you do.  If the cable is certified as
getting all the bits to the other end under whatever environmental
conditions specified by the HDMI people, then it's going to work for
the 99% of people with normal requirements.</p>

<p>Nobody wants to make a significant investment in a piece of
audio-visual equipment and feel they are getting something that isn't
optimal.  Harvey Norman's use of this understandable consumer
sentiment to sell ridiculously over-priced cables that do nothing is
extremely disappointing.</p>

<p>I'm sure the commissions on these things encourage this behaviour,
so it is useless expecting the retailer or individual sales assistant
to change their policy to recommend reasonably priced cables.
However, it is really Tivo and other manufacturers who get the raw end
of this deal; a $130 cable is over 20% of the price the actual Tivo!
That is surely affecting people's purchasing decisions.</p>

<p>If Tivo and others included a certified HDMI cable with their
device, as they do with component cables, and had "Certified HDMI 1.3
cable included" plastered on the box, it would be a harder sell to
explain why the manufacturer would bother shipping a certified cable
that is supposedly insufficient, and consumers would hopefully avoid
the very distasteful high-pressure theatrics I was subjected to
today.</p>

<p><b>Update:</b> I have removed my description of the individual
salesman in the title.  Singling someone out invites ad hominem
attacks and I have no interest in providing a forum for or
perpetuating any such thing.</p>

<p>If it's one salesman, it's a thousand.  To reiterate my main point,
manufacturers must surely be annoyed that they participate in price
wars with each other only to have their margins taken by a gold-plated
optical cable company.  I believe it is really up to them to get the
information into their own market so it can operate efficiently.</p>

]]></content:encoded><category domain="http://www.technovelty.org">general</category><dc:date>2009-12-22T09:23:00Z</dc:date></item><item><title>Distance to 1 million people</title><guid isPermaLink="false">general/distance-to-1-million.html</guid><link>http://www.technovelty.org/general/distance-to-1-million.html</link><description>On a recent trip up the Oregon coast, a friendly doorman at our hotel in Portland was inquiring about our ...</description><content:encoded><![CDATA[
<p>On a recent trip up the Oregon coast, a friendly doorman at our
hotel in Portland was inquiring about our trip.  When we mentioned we
passed through Bandon, OR, he quipped that Bandon was the place
furthest from a city of one million people in the USA.  I guess a
normal person would just think "oh, that's interesting" and move on,
but it has been plaguing me ever since.</p>

<p>Firstly, I had to find what cities in the USA had more than 1
million people.  Luckily <a
href="http://www.wolframalpha.com/">Wolfram Alpha</a> gives the answer:</p>

<ul>
<li>Chicago,Illinois</li>
<li>Dallas,Texas</li>
<li>Houston,Texas</li>
<li>Los Angeles,California</li>
<li>New York, New York</li>
<li>Philadelphia,Pennsylvania</li>
<li>Phoenix,Arizona</li>
<li>San Antonio,Texas</li>
<li>San Diego,California</li>
</ul>

<p>(I certainly wouldn't have guessed that list!)  From there my plan
was to find the bounding box of the continental USA; luckily <a
href="http://en.wikipedia.org/wiki/Extreme_points_of_the_United_States">Wikipedia</a>
has the raw data for that.  Combined with the latitude and longitude
of the cities above, I had the raw data.</p>

<p>I couldn't figure out any way better than a simple brute-force of
testing every degree and minute of latitude and longitude within the
bounding box and calculating the distance to the closest large city;
the theory being that from one particular point you would have to
travel further than any other to reach a city of 1 million people.
Luckily, that is short work for a modern processor, and hopefully the
result would be a point somewhere around Bandon.  I'd already become
acquainted with the great circle and measuring distances when I did <a
href="http://www.tinymap.net">Tinymap</a>, so a quick <a
href="http://www.wienand.org/junkcode/python/usa-dist.py">python
program</a> evolved.</p>

<p>However, it turns out that the program picks the far south-east
corner of the bounding box.  Thanks to the shape of the USA, that is
way out over the ocean somewhere.  I can't figure out a way to get an
outline of the USA to test if a given point is inside the border or
not, but all is not lost.</p>

<p>I modified the program to output the the distance to the closest
large city along with the location to a log file, and then imported it
into gnuplot to make a heat-map.  The hardest part was finding an
equirectangular outline of the USA to place the heat-map over, rather
than a much more common Mercator projection; <a
href="http://commons.wikimedia.org/wiki/File:Usa-equidistant.png">Wikimedia</a>
to the rescue!</p>

<p>I actually surprised myself at how well the two lined up when,
after a little work with Gimp, I overlayed them (<a
href="http://www.technovelty.org/images/usa-one-million-distance-big.png">big</a>)</p>

<img src="http://www.technovelty.org/images/usa-one-million-distance.jpg"
     alt="Distance to a city of 1 million people (km)" />

<p>From this, I can see that Bandon, about a third of the way up the
Oregon coast, is a pretty good candidate.  However, probably not the
best; I get the feeling the real point that is the furthest from any
city of 1 million people is actually somewhere in the central-middle
of Montana.</p>

<p>However, we can also fiddle the program slightly to disprove the
point about Bandon.  The numbers show the closest large city to Bandon
is LA, at ~1141km.  Taking another point we suspect to be more remote;
the closest large city to Portland (where we met the doorman) is also
LA at ~1329km.  So to reach the closest large city you have to travel
further from Portland than Bandon, so Bandon is <i>not</i> the
furthest place in the USA from a city of one million people.  Myth
busted!</p>
]]></content:encoded><category domain="http://www.technovelty.org">general</category><dc:date>2009-12-06T00:28:00Z</dc:date></item><item><title>Go L4!</title><guid isPermaLink="false">code/go-l4.html</guid><link>http://www.technovelty.org/code/go-l4.html</link><description>By now everybody has now heard about Go , Google's expressive, concurrent, garbage collecting language. One big, glaring thing stuck ...</description><content:encoded><![CDATA[
<p>By now everybody has now heard about <a
href="http://golang.org/">Go</a>, Google's expressive, concurrent,
garbage collecting language.  One big, glaring thing stuck out at me
when I was reading the documentation:</p>

<blockquote>
Do not communicate by sharing memory; instead, share memory by communicating.
</blockquote>

<p>One of the examples given is a semaphore using a channel, which
I'll copy here for posterity.</p>

<div class="codebox">
<pre>
var sem = make(chan int, MaxOutstanding)

func handle(r *Request) {
    sem &lt;- 1;    // Wait for active queue to drain.
    process(r);  // May take a long time.
    &lt;-sem;       // Done; enable next request to run.
}

func Serve(queue chan *Request) {
    for {
        req := &lt;-queue;
        go handle(req);  // Don't wait for handle to finish.
    }
}
</pre>
</div>

<p>Here is a little illustration of that in operation.</p>

<center>
<img src="http://www.technovelty.org/images/go-semaphore.png" alt="Semaphores with Google Go" />
</center>

<p> <tt>Serve</tt> creates <i>goroutines</i> via the <tt>go</tt>
keyword; each of which tries to get a slot in the channel.  In the
example there are only 3 slots, so it acts like a semaphore of count
3.  When done, each thread returns its slot to the channel, which
allows anyone blocked to be woken and continued.</p>

<p>This instantly reminded me of the very first thing you need to do
if you ever want to pass <a
href="http://www.cse.unsw.edu.au/~cs9242/current/">Advanced Operating
Systems</a> -- write a semaphore server to provide synchronisation
within your OS.</p>

<p>In <a href="http://www.ok-labs.com/">L4</a>, threads communicate
with each other via <i>inter-process communication</i> (IPC).  IPC
messages have a fixed format - you specify a target thread, bundle
some data into the available slots in the IPC format and fire it off.
By default you block waiting for a reply -- this all happens within a
single call for efficiency.  On the other side, you can write servers
who are listening for remote IPC connections, where everything happens
in reverse.</p>

<p>Here's another illustration the of the trivial semaphore server
concept <a href="http://twitter.com/shehjart">Shehjar</a> and I
implemented.</p>

<center>
<img src="http://www.technovelty.org/images/l4-semaphore.png" alt="L4 semaphore server example" />
</center>

<p>Look familiar?  Instead of a blocking push of a number into a slot
into a channel, you make a blocking IPC call to a remote server.</p>

<p>My point here is that both take the approach of sharing memory via
communication.  When using IPC, you bundle up all your information
into the available slots in the IPC message and send it.  When using a
channel, you bundle your information into an entry in the channel and
call your goroutine.  Receiving the IPC is the same as draining a
channel - both result in you getting the information that was bundled
into it by the caller.</p>

<table border="1">
<tr><th>IPC</th><th>Go</th></tr>

<tr><td>Start thread</td><td>Start goroutine</td></tr>
<tr><td>New thread blocks listening for IPC message</td><td>Goroutine blocks draining empty channel</td></tr>
<tr><td>Bundle information into IPC message</td><td>Bundle data into type of your channel</td></tr>
<tr><td>Send IPC to new thread</td><td>Push data into channel</td></tr>
<tr><td>Remote thread unbundles IPC</td><td>goroutine drains channel and gets data</td></tr>
</table>

<p>Whenever you mention the word "microkernel", people go off the
deep-end and one thing they seem to forget about is the inherent
advantages of sharing state only via communication.  As soon as you do
that, you've broken open an amazing new tool for concurrency, which is
now implicitly implied.  By communicating via messages/channels rather
than shared global state, it doesn't matter where you run!  One of
those threads in the example could be running on another computer in
your cloud, marshalling up it's IPC messages/channel entries and
sending them over TCP/IP -- nobody would care!</p>

<p>At any rate, <i>do not communicate by sharing memory; instead,
share memory by communicating</i> is certainly an idea whose time has
come.</p>
]]></content:encoded><category domain="http://www.technovelty.org">code</category><dc:date>2009-11-20T00:37:00Z</dc:date></item><item><title>Django toolchain on Debian</title><guid isPermaLink="false">linux/debian/django-toolchain.html</guid><link>http://www.technovelty.org/linux/debian/django-toolchain.html</link><description>Although Django is well packaged for Debian, I've recently come to the conculsion that the packages are really not what ...</description><content:encoded><![CDATA[
<p>Although Django is well packaged for Debian, I've recently come to
the conculsion that the packages are really not what I want.  The
problem is that my server runs Debian stable, while my development
laptop runs unstable, and Django revisions definitely fall into the
"unstable" category.  There really is no way to use a system Django
1.1 on one side, and a system Django 1.0 on the other.</p>

<p>After a bit of work, I think I've got something together that
works, and I post it here in the hope it is useful for someone else.
This info has been gleaned from similar references such as <a
href="http://www.danceric.net/2009/03/26/django-virtualenv-and-mod_wsgi/">this</a>
and <a
href="http://www.saltycrane.com/blog/2009/05/notes-using-pip-and-virtualenv-django/">this</a>.</p>

<p>This is aimed at running a server using Debian stable (5.0) for
production and an unstable environment for development.  You actually
need both to get this running.  This is based on a project called
"project" that lives in <tt>/var/www</tt></p>

<ol>
<li>First step is to install <tt>python-virtualenv</tt> on both.</li>

<li>Create a virtualenv on both, using the <tt>--no-site-packages</tt>
to make it a stand-alone environment.  This is like a chroot for
python.

<div class="codebox">
<pre>
$ virtualenv --no-site-packages project
New python executable in project/bin/python
Installing setuptools............done.
</pre>
</div>

</li>

<li>The <i>unstable</i> environment has a file you'll need to copy
into the <i>stable</i> environment - <tt>bin/activate_this.py</tt>.
The stable version of <tt>python-virtualenv</tt> isn't recent enough
to include this file, but you need it to essentially switch the system
python into the chrooted environment.  This will come in handy later
when setting up the webserver.</li>

<li>There are probably better ways to keep the two environments in
sync, but I simply take a manual approach of doing everything twice,
once in each.  So from now on, do the following in both
environments.</li>

<li>Activate the environment

<div class="codebox">
<pre>
/var/www$ cd project
/var/www/project$ . bin/activate
(project) /var/www/project$
</pre>
</div>

</li>

<li>Use <tt>easy_install</tt> to install <tt>pip</tt>

<div class="codebox">
<pre>
(project) /var/www/project$ easy_install pip
Searching for pip
Reading http://pypi.python.org/simple/pip/
Reading http://pip.openplans.org
Best match: pip 0.4
Downloading http://pypi.python.org/packages/source/p/pip/pip-0.4.tar.gz#md5=b45714d04f8fd38fe8e3d4c7600b91a2
Processing pip-0.4.tar.gz
Running pip-0.4/setup.py -q bdist_egg --dist-dir /tmp/easy_install-Wu9O-U/pip-0.4/egg-dist-tmp-xjSdxq
warning: no previously-included files matching '*.txt' found under directory 'docs/_build'
no previously-included directories found matching 'docs/_build/_sources'
zip_safe flag not set; analyzing archive contents...
pip: module references __file__
Adding pip 0.4 to easy-install.pth file
Installing pip script to /var/www/project/bin

Installed /var/www/project/lib/python2.5/site-packages/pip-0.4-py2.5.egg
Processing dependencies for pip
Finished processing dependencies for pip
</pre>
</div>
</li>

<li>Install <tt>setuptools</tt>, also using <tt>easy_install</tt> (for
some reason, <tt>pip</tt> can't install it).  There is a trick here,
you need to specify at least version 0.6c9 or there will be issues
with the SVN version on Debian stable when you try to get Django in
the next step.

<div class="codebox">
<pre>
(project) /var/www/project$ easy_install setuptools==0.6c9
Searching for setuptools==0.6c9
Reading http://pypi.python.org/simple/setuptools/
Best match: setuptools 0.6c9
Downloading http://pypi.python.org/packages/2.5/s/setuptools/setuptools-0.6c9-py2.5.egg#md5=fe67c3e5a17b12c0e7c541b7ea43a8e6
Processing setuptools-0.6c9-py2.5.egg
Moving setuptools-0.6c9-py2.5.egg to /var/www/project/lib/python2.5/site-packages
Removing setuptools 0.6c8 from easy-install.pth file
Adding setuptools 0.6c9 to easy-install.pth file
Installing easy_install script to /var/www/project/bin
Installing easy_install-2.5 script to /var/www/project/bin

Installed /var/www/project/lib/python2.5/site-packages/setuptools-0.6c9-py2.5.egg
Processing dependencies for setuptools==0.6c9
Finished processing dependencies for setuptools==0.6c9
</pre>
</div>
</li>

<li>Create a <tt>requirements.txt</tt> with the path to the Django
SVN for <tt>pip</tt> to install, then and then install it.

<div class="codebox">
<pre>
(project) /var/www/project$ cat requirements.txt
-e svn+http://code.djangoproject.com/svn/django/tags/releases/1.0.3/#egg=Django
(project) /var/www/project$ pip install -r requirements.txt
Obtaining Django from svn+http://code.djangoproject.com/svn/django/tags/releases/1.0.3/#egg=Django (from -r requirements.txt (line 1))
  Checking out http://code.djangoproject.com/svn/django/tags/releases/1.0.3/ to ./src/django

(project) /var/www/project$ pip install -r requirements.txt
Obtaining Django from svn+http://code.djangoproject.com/svn/django/tags/releases/1.0.3/#egg=Django (from -r requirements.txt (line 1))
  Checking out http://code.djangoproject.com/svn/django/tags/releases/1.0.3/ to ./src/django
... so on ...
</pre>
</div>
</li>

<li>Almost there!  You can keep installing more Python requirements
with <tt>pip</tt> if you need, but we've got enough here to
start.</li>

<li>Create a file in <tt>/var/www/project</tt> called
<tt>project-python.py</tt>.  This will be the Python interpreter the
webserver uses, and basically exec's itself into the virtalenv.  The
file should contain the following:

<div class="codebox">
<pre>
activate_this = "/var/www/project/bin/activate_this.py"
execfile(activate_this, dict(__file__=activate_this))

from django.core.handlers.modpython import handler
</pre>
</div>
</li>

<li>Now it's time to start the Django project.  I like to create a new
directory called <tt>project</tt>, which will be the parent directory
kept in the SCM with all the code, media, templates, database (if
using SQLite) etc.  In this way to keep the two environments
up-to-date I simply <tt>svn ci</tt> on one side, and <tt>svn co</tt>
on the other.

<div class="codebox">
<pre>
(project) /var/www/project$ mkdir project
(project) /var/www/project/project$ mkdir db django media www
(project) /var/www/project/project$ cd django/
(project) /var/www/project/project/django$ django-admin startproject myproject
</pre>
</div>

</li>

<li>Last step now is to wire-up Apache to serve it all up.  The magic
is making sure you specify the correct <tt>PythonHandler</tt> that you
made before to use the virtualenv, and include the right paths so you
can find it and all the required Django settings.

<div class="codebox">
<pre>
DocumentRoot /var/www/project

&lt;Location "/"&gt;
    SetHandler python-program
    PythonHandler project-python
    PythonPath "['/var/www/project/','/var/www/project/project/django/'] + sys.path"
    SetEnv DJANGO_SETTINGS_MODULE myproject.settings
    PythonDebug On
&lt;/Location&gt;

Alias /media /var/www/project/project/media
&lt;Location "/media"&gt;
    SetHandler none
&lt;/Location&gt;
&lt;Directory "/var/www/project/project/media"&gt;
    AllowOverride none
    Order allow,deny
    Allow from all
    Options FollowSymLinks Indexes
&lt;/Directory&gt;
</pre>
</div>

</li>

</ol>

<p>With all this, you should be up and running in a basic but stable
environment.  It's easy enough to update packages for security fixes,
etc via <tt>pip</tt> after activating your virtualenv.</p>


]]></content:encoded><category domain="http://www.technovelty.org">linux/debian</category><dc:date>2009-09-11T12:49:00Z</dc:date></item><item><title>SIGTTOU and switching to canonical mode</title><guid isPermaLink="false">linux/tips/sigttou.html</guid><link>http://www.technovelty.org/linux/tips/sigttou.html</link><description>Here's an interesting behaviour that, as far as I can tell, is completley undocumented, sightly consfusing but fairly logical. Your ...</description><content:encoded><![CDATA[
<p>Here's an interesting behaviour that, as far as I can tell, is
completley undocumented, sightly consfusing but fairly logical.  Your
program should receive a SIGTTOU when it is running in the background
and attempts to output to the terminal -- the idea being that you
shouldn't scramble the output by mixing it in while the shell is
trying to operate.  Here's what the bash manual has to say</p>

<div class="codebox">
<pre>
Background processes are those whose process group ID differs from the
terminal's; such processes are immune to key- board-generated signals.
Only foreground processes are allowed to read from or write to the
terminal.  Background processes which attempt to read from (write to)
the terminal are sent a SIGTTIN (SIGTTOU) signal by the terminal
driver, which, unless caught, suspends the process.
</pre>
</div>

<p>So, consider the following short program, which writes some output
and catches any SIGTTOU's, with an optional flag to switch between
canonical and non-canonical mode.</p>

<div class="codebox">
<pre>
#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;signal.h&gt;
#include &lt;termios.h&gt;
#include &lt;unistd.h&gt;

static void sig_ttou(int signo) {
   printf("caught SIGTTOU\n");
   signal(SIGTTOU, SIG_DFL);
   kill(getpid(), SIGTTOU);
}

int main(int argc, char *argv[]) {

   signal(SIGTTOU, sig_ttou);

   if (argc != 1) {
      struct termios tty;

      printf("setting non-canoncial mode\n");
      tcgetattr(fileno(stdout), &amp;tty);
      tty.c_lflag &amp;= ~(ICANON);
      tcsetattr(fileno(stdout), TCSANOW, &amp;tty);
   }

   int i = 0;
   while (1) {
      printf("  *** %d ***\n", i++);
      sleep(1);
   }
}
</pre>
</div>

<p>This program ends up operating in an interesting manner.</p>

<ol>
<li>Run in the background, canonical mode : no SIGTTOU and output gets multiplexed with shell.

<div class="codebox">
<pre>
$ ./sigttou &amp;
  *** 0 ***
[1] 26171
$   *** 1 ***
  *** 2 ***
  *** 3 ***
</pre>
</div>

</li>

<li>Run in the background, non-canonical mode : SIGTTOU delivered

<div class="codebox">
<pre>
$ ./sigttou 1 &amp;
[1] 26494
ianw@jj:/tmp$ setting non-canoncial mode
caught SIGTTOU


[1]+  Stopped                 ./sigttou 1
</pre>
</div>
</li>

<li>Run in the background, canonical mode, tostop set via stty :
SIGTTOU delivered, seemingly <i>after</i> a write proceeds

<div class="codebox">
<pre>
$ stty tostop
$ ./sigttou &amp;
[2] 26531
ianw@jj:/tmp$   *** 0 ***
caught SIGTTOU


[2]+  Stopped                 ./sigttou
</pre>
</div>

</li>
</ol>

<p>You can see a practical example of this by comparing the difference
between <code>cat file &amp;</code> and <code>more file &amp;</code>.
The semantics make some sense -- anything switching off canonical mode
is like to be going to really scramble your terminal, so it's good to
stop it and let it's terminal handling functions run.  I'm not sure
why canoncial background is considered useful mixed in with your
prompt, but someone, somewhere must have decided it was so.</p>

<p><b>Update</b>: upon further investigation, it is the switching of
terminal modes that invokes the SIGTTOU.  To follow the logic through
more, see the various users of <a
href="http://lxr.linux.no/#linux+v2.6.31/drivers/char/tty_io.c#L345">tty_check_change</a>
in the tty driver.</p>
]]></content:encoded><category domain="http://www.technovelty.org">linux/tips</category><dc:date>2009-08-21T01:02:00Z</dc:date></item><item><title>Using frozen chocolate to visualise microwave heat distribution</title><guid isPermaLink="false">humor/chocolate.html</guid><link>http://www.technovelty.org/humor/chocolate.html</link><description>My attempt at answering that most important of questions : where should one place their plate in the microwave to ...</description><content:encoded><![CDATA[
<p>My attempt at answering that most important of questions : where
should one place their plate in the microwave to achieve maximal
heating?</p>

<div style="text-align: center; margin: auto"><object type="application/x-shockwave-flash" style="width:640px; height:385px;" data="http://www.youtube.com/v/-4juszqMaYA">
<param name="movie" value="http://www.youtube.com/v/-4juszqMaYA" />
</object></div>
]]></content:encoded><category domain="http://www.technovelty.org">humor</category><dc:date>2009-07-23T02:23:00Z</dc:date></item><item><title>Review : The Race for a New Game Machine</title><guid isPermaLink="false">code/arch/game-machine.html</guid><link>http://www.technovelty.org/code/arch/game-machine.html</link><description>I recently finished The Race for a New Game Machine: Creating the Chips Inside the XBox 360 and the Playstation ...</description><content:encoded><![CDATA[
<p>I recently finished <a
href="http://www.amazon.com/Race-New-Game-Machine-Playstation/dp/0806531010">The
Race for a New Game Machine: Creating the Chips Inside the XBox 360
and the Playstation 3</a> (David Shippy and Mickie Phipps); an
interesting insight into the processor development process from some
of the lead architects.</p>

<p>The executive summary is : Sony, Toshiba and IBM (STI) decided to
get together to create the core of the Playstation 3 &mdash; the Cell
processor.  Sony, with their graphics and gaming experience, would do
the <i>Synergistic Processing Elements</i>; extremely fast but limited
sub-units specialising in doing 3D graphics and physics work
(i.e. great for games).  IBM would do a Power based core that handled
the general purpose computing requirements.</p>

<p>The twist comes when Microsoft came along to IBM looking for the
Xbox 360 processor, and someone at IBM mentioned the Power core that
was being worked on for the Playstation.  Unsurprisingly, the features
being built for the Playstaion also interested Microsoft, and the next
thing you know, IBM is working on the same core for Microsoft and Sony
at the same time, without telling either side.</p>

<p>This whole chain of events makes for a very interesting story.  The
book is written for a general audience, but you'll probably get the
most out of it if you already have some knowledge of computer
architecture; if you're trying to understand some of the concepts
referred to from the two line descriptions you'll get a bit lost
(H&amp;P it is not).</p>

<p>The only small criticism is that it sometimes falls into reading a
bit like a long LinkedIn recommendation.  However, the book is very
well paced, and throws in just enough technical tidbits amongst the
corporate and personal dramas to make it a very fun read.</p>

<p>One thing that is talked about a bit is the <i>fan-out of four</i>
(FO4) metric used in the designers quest to push the chip as fast as
possible (and, as mentioned many times in the book, faster than what
Intel could do!).  I thought it might be useful to expand on this
interesting metric a bit.</p>

<h4>FO4</h4>

<p>One problem facing chip architects is that, thanks to Moore's Law,
it is hard to find a constant to compare design versus implementation.
For example, you may design an amazing logic-block to factor large
integers into products of prime numbers, but somebody else with better
fabrication facilities might be able to essentially brute-force a
better solution by producing faster hardware using a much less
innovative design.</p>

<p>Some metric is needed that can compare the two designs discounting
who has the better fabrication process.  This is where the FO4 comes
in.</p>

<p>When you change the input to a logic gate, it is not like it
magically flips the output to the correct level instantaneously.
There is a latency while everything settles to its correct level
&mdash; the gate delay.  The more gates connected to the output of a
gate the more current required, which has additional effects on
latency.  The FO4 latency is defined as the time required to flip an
inverter gate connected to (fanned-out) to four other inverter
gates.</p>

<center>
<img src="http://www.technovelty.org/images/fo4.png" alt="Fan-out of four"></img>
</center>

<p>Thus you can describe the latency of other logic blocks in
multiples of FO4 latencies.  As this avoids measuring against
wall-time it is an effective description of the relative efficiency of
logic designs.  For example, you may calculate that your factoriser
has a latency of 100 FO4.  Just because someone else's 200 FO4
factoriser gets a result a few microseconds faster thanks to their
fancy ultra-low-FO4-latency fabrication process, you can still show
that your design, at least a priori, is better.</p>

<p>The book refers several times to efforts to reduce the FO4 of the
processor as much as possible.  The reason this is important in this
context is that the maximum latency on the critical path will
determine the fastest clock speed you can run the processor at.  For
reasons explained in the book high clock speed was a primary goal, so
every effort had to be made to reduce latencies.</p>

<p>All modern processors operate as a production line, with each stage
doing some work and passing it on to the next stage.  Clearly the
slowest stage determines the maximum speed that the production line
can run at (weakest link in the chain and all that).  For example, if
you clock at 1Ghz, that means each cycle takes 1 nanosecond (1s /
1,000,000,000Hz).  If you have a F04 latency of say, 10 picoseconds,
that means any given stage can have a latency of no more than 100 FO4
&mdash; otherwise that stage would not have enough time to settle and
actually produce the correct result.</p>

<p>Thus the smaller you can get the FO4 latencies of your various
stages, the higher you can safely up the clock speed.  One way around
long latencies might be to split-up your logic into smaller stages,
making a much longer pipeline (production line).  For example, split
your 100 FO4 block into two 50 FO4 stages.  You can now clock the
processor higher, but this doesn't necessarily mean you'll get actual
results out the end of the pipeline any faster (as Intel discovered
with the Pentium 4 and it's notoriously long pipelines and
corresponding high clock rates).</p>

<p>Of course, this doesn't even begin to describe the issues with
superscalar design, instruction level parallelism, cache interaction
and the myriad of other things the architects have to consider.</p>

<p>Anyway, after reading this book I guarantee you'll have an
interesting new insight the next time you fire-up Guitar Hero.</p>
]]></content:encoded><category domain="http://www.technovelty.org">code/arch</category><dc:date>2009-07-15T09:15:00Z</dc:date></item><item><title>Dig Jazz Applet, V2</title><guid isPermaLink="false">code/gnome/dig-jazz-applet-v2.html</guid><link>http://www.technovelty.org/code/gnome/dig-jazz-applet-v2.html</link><description>It seems the ABC updated the DIG Jazz now-playing list format, breaking V1. Some quick flash disassembly and a bit ...</description><content:encoded><![CDATA[
<p>It seems the ABC updated the <a href="www.abc.net.au/dig/jazz/">DIG
Jazz</a> now-playing list format, breaking V1.  Some quick flash
disassembly and a bit of hacking, and order is restored.  As a bonus,
it now shows the upcoming songs.</p>

<center>
<img src="http://www.technovelty.org/images/dig-jazz-applet-v2.png" alt="DIG Jazz now-playing Gnome applet" />
</center>

<p><a href="http://www.wienand.org/junkcode/dig-jazz-applet/">Source</a> or
<a href="http://www.wienand.org/junkcode/dig-jazz-applet/dig-jazz-applet_2.0-1_all.deb">Debian package</a>.</p>
]]></content:encoded><category domain="http://www.technovelty.org">code/gnome</category><dc:date>2009-05-18T13:20:00Z</dc:date></item><item><title>Quickly describing hash utilisation</title><guid isPermaLink="false">code/hash-ratio.html</guid><link>http://www.technovelty.org/code/hash-ratio.html</link><description>I think the most correct way to describe utilisation of a hash-table is using chi-squared distributions and hypothesis and degrees ...</description><content:encoded><![CDATA[
<p>I think the most correct way to describe utilisation of a hash-table
is using chi-squared distributions and hypothesis and degrees of
freedom and a bunch of other things nobody but an actuary remembers.
So I was looking for a quick method that was close-enough but didn't
require digging out a statistics text-book.</p>

<p>I'm sure I've re-invented some well-known measurement, but I'm not
sure what it is.  The idea is to add up the total steps required to
look-up all elements in the hash-table, and compare that to the
theoretical ideal of a uniformly balanced hash-table.  You can then
get a ratio that tells you if you're in the ball-park, or if you
should try something else.  A diagram should suffice.</p>

<img src="http://www.technovelty.org/images/hash-utilisation.png"
alt="Scheme for acquiring a hash-utilisation ratio" />

<p>This seems to give quite useful results with a bare minimum of
effort, and most importantly no tricky floating point math.  For
example, on the standard Unix <tt>words</tt> with a 2048 entry
hash-table, the standard DJB hash came out very well (as expected)</p>

<div class="codebox">
<pre>
Ideal 2408448
Actual 2473833
----
Ratio 0.973569
</pre>
</div>

<p>To contrast, a simple "add each character" type hash:</p>

<div class="codebox">
<pre>
Ideal 2408448
Actual 6367489
----
Ratio 0.378241
</pre>
</div>

<p>Example code is <a
href="http://www.wienand.org/junkcode/python/hash-ratio.py">hash-ratio.py</a>.
I expect this measurement is most useful when you have a largely
static bunch of data for which you are attempting to choose an
appropriate hash-function.  I guess if you are really trying to hash
more or less random incoming data and hence only have a random sample
to work with, you can't avoid doing the "real" statistics.</p>
]]></content:encoded><category domain="http://www.technovelty.org">code</category><dc:date>2009-05-07T06:37:00Z</dc:date></item><item><title>Relocation truncated to fit - WTF?</title><guid isPermaLink="false">code/c/relocation-truncated.html</guid><link>http://www.technovelty.org/code/c/relocation-truncated.html</link><description>If you code for long enough on x86-64, you'll eventually hit an error such as: (.text+0x3): relocation truncated to fit: ...</description><content:encoded><![CDATA[
<p>If you code for long enough on x86-64, you'll eventually hit an
error such as:</p>

<div class="codebox">
<pre>
(.text+0x3): relocation truncated to fit: R_X86_64_32S against symbol `array' defined in foo section in ./pcrel8.o
</pre>
</div>

<p>Here's a little example that might help you figure out what you've
done wrong.</p>

<p>Consider the following code:</p>

<div class="codebox">
<pre>
<b>$ cat foo.s</b>
.globl foovar
  .section   foo, "aw",@progbits
  .type foovar, @object
  .size foovar, 4
foovar:
   .long 0

.text
.globl _start
 .type function, @function
_start:
  movq $foovar, %rax
</pre>
</div>

<p>In case it's not clear, that would look something like:</p>

<div class="codebox">
<pre>
int foovar = 0;

void function(void) {
  int *bar = &amp;foovar;
}
</pre>
</div>

<p>Let's build that code, and see what it looks like</p>

<div class="codebox">
<pre>
<b>$ gcc -c foo.s</b>

<b>$ objdump --disassemble-all ./foo.o</b>

./foo.o:     file format elf64-x86-64


Disassembly of section .text:

0000000000000000 &lt;_start&gt;:
   0:		 48 c7 c0 00 00 00 00	mov    $0x0,%rax

Disassembly of section foo:

0000000000000000 &lt;foovar&gt;:
   0:		 00 00			add    %al,(%rax)
   ...
</pre>
</div>

<p>We can see that the <tt>mov</tt> instruction has only allocated 4
bytes (<tt>00 00 00 00</tt>) for the linker to put in the address of
<tt>foovar</tt>.  If we check the relocations:</p>

<div class="codebox">
<pre>
<b>$ readelf --relocs ./foo.o</b>

Relocation section '.rela.text' at offset 0x3a0 contains 1 entries:
  Offset          Info           Type           Sym. Value    Sym. Name + Addend
000000000003  00050000000b R_X86_64_32S      0000000000000000 foovar + 0
</pre>
</div>

<p>The <tt>R_X86_64_32S</tt> relocation is indeed only a 32-bit
relocation.  Now we can tickle this error.  Consider the following
linker script, which puts the <tt>foo</tt> section about 5 gigabytes
away from the code.</p>

<div class="codebox">
<pre>
<b>$ cat test.lds</b>
SECTIONS
{
 . = 10000;
 .text : { *(.text) }
 . = 5368709120;
 .data : { *(.foo) }
}
</pre>
</div>

<p>This now means that we can not fit the address of <tt>foovar</tt>
inside the space allocated by the relocation.  When we try it:</p>

<div class="codebox">
<pre>
<b>$ ld -Ttest.lds ./foo.o</b>
./foo.o: In function `_start':
(.text+0x3): relocation truncated to fit: R_X86_64_32S against symbol `foovar' defined in foo section in ./foo.o
</pre>
</div>

<p>What this means is that the full 64-bit address of <tt>foovar</tt>,
which now lives somewhere above 5 gigabytes, can't be represented
within the 32-bit space allocated for it.</p>

<p>For code optimisation purposes, the default immediate size to the
<tt>mov</tt> instructions is a 32-bit value.  This makes sense
because, for the most part, programs can happily live within a 32-bit
address space, and people don't do things like keep their data so far
away from their code it requires more than a 32-bit address to
represent it.  Defaulting to using 32-bit immediates therefore cuts
the code size considerably, because you don't have to make room for a
possible 64-bit immediate for every <tt>mov</tt>.</p>

<p>So, if you want to <i>really</i> move a full 64-bit immediate into
a register, you want the <tt>movabs</tt> instruction.  Try it out with
the code above - with <tt>movabs</tt> you should get a
<tt>R_X86_64_64</tt> relocation and 64-bits worth of room to patch up
the address, too.</p>

<p>If you're seeing this and you're not hand-coding, you probably want
to check out the <tt>-mmodel</tt> argument to <tt>gcc</tt>.</p>
]]></content:encoded><category domain="http://www.technovelty.org">code/c</category><dc:date>2009-03-12T12:20:00Z</dc:date></item><item><title>YUI ButtonGroup Notes</title><guid isPermaLink="false">web/yui-buttongroup.html</guid><link>http://www.technovelty.org/web/yui-buttongroup.html</link><description>Some tips and things to check if your YUI ButtonGroup isn't behaving as you wish it would. Double-check your &lt;body&gt; ...</description><content:encoded><![CDATA[
<p>Some tips and things to check if your <a
href="http://developer.yahoo.com/yui/button/#usingbuttongroup">YUI
ButtonGroup</a> isn't behaving as you wish it would.</p>

<ul>
<li><p>Double-check your <tt>&lt;body&gt;</tt> tag has <tt>class="yui-skin-sam"</tt></p></li>

<li><p>Unlike in the documentation example, you can't just put a call
to <tt>YAHOO.widget.ButtonGroup</tt> pointing to your <tt>div</tt>
anywhere in your HTML and expect it to work.  You've got to wait for
it to be ready with something like:</p>

<div class="codebox">
<pre>
&lt;script type="text/javascript"&gt;
YAHOO.util.Event.onContentReady("my_button_div", function() {
  var oButtonGroup = new YAHOO.widget.ButtonGroup("my_button_div");
});
&lt;/script&gt;
</pre>
</div>
</li>

<li><p>You can easily get an image in each button.  For example, if
your button is defined as:</p>

<div class="codebox">
<pre>
 &lt;span id="my-button-id" class="yui-button yui-radio-button yui-button-checked"&gt;
  &lt;span class="first-child"&gt;
    &lt;button type="button" hidefocus="true"&gt;&lt;/button&gt;
  &lt;/span&gt;
 &lt;/span&gt;
</pre>
</div>

<p>Simply add a CSS class something like:</p>

<div class="codebox">
<pre>
.yui-button#my-button-id button { background:url(http://server/image.jpg) 50% 50% no-repeat; }
</pre>
</div>

</li>

</ul>

<p>Hopefully, this will save someone else a few hours!</p>
]]></content:encoded><category domain="http://www.technovelty.org">web</category><dc:date>2009-03-02T12:36:00Z</dc:date></item></channel></rss>
