How do I print debug messages to gdb console with STM32 discovery board using GDB, OpenOCD and arm-none-eabi-gcc?
Thanks for the pointers, markt and chris-stratton. The semihosting option turned out to be quite straightforward. I managed to find the source for a couple of simple logging routines that can send messages to the OpenOCD console. I'll post them here since (i) they required some modification to work and (ii) I think this info is not super easy to find for people who are just starting out.

First, the D code here is easily adapted to provide the following C function:

void send_command(int command, void *message)
{
   asm("mov r0, %[cmd];"
       "mov r1, %[msg];"
       "bkpt #0xAB"
         :
         : [cmd] "r" (command), [msg] "r" (message)
         : "r0", "r1", "memory");
}


Example of calling send_command to write a string to the OpenOCD console:

const char s[] = "Hello world\n";
uint32_t m[] = { 2/*stderr*/, (uint32_t)s, sizeof(s)/sizeof(char) - 1 };
send_command(0x05/* some interrupt ID */, m);


Second, the putChar function given in the comments here works fine, except that I had to add a '#' before 0x03:

void put_char(char c)
{
    asm (
    "mov r0, #0x03\n"   /* SYS_WRITEC */
    "mov r1, %[msg]\n"
    "bkpt #0xAB\n"
    :
    : [msg] "r" (&amp;c)
    : "r0", "r1"
    );
}


To look at the output from these functions, 
I first start up OpenOCD, then connect using arm-none-eabi-gdb as follows:

target remote localhost:3333
monitor arm semihosting enable
monitor reset halt
load code.elf
continue


Note that the messages appear on the stdout of the OpenOCD process, not at the GDB console.