Commit 55f2fe83 authored by ntfreak's avatar ntfreak
Browse files

- removed flash write_image - binary compare function has been moved to verify_image command

- minor code reformat and cleanup
- updated docs to include new commands

git-svn-id: svn://svn.berlios.de/openocd/trunk@243 b42882b7-edfa-0310-969c-e2dbd0fdcd60
parent 79f25814
......@@ -4,8 +4,12 @@
@settitle Open On-Chip Debugger (openocd)
@c %**end of header
@include version.texi
@titlepage
@title Open On-Chip Debugger (openocd)
@subtitle Edition @value{EDITION} for openocd version @value{VERSION}
@subtitle @value{UPDATED}
@page
@vskip 0pt plus 1filll
@end titlepage
......@@ -15,7 +19,8 @@
@node Top, About, , (dir)
@top OpenOCD
The Manual always document the latest version of OpenOCD available from SVN.
This is edition @value{EDITION} of the openocd manual for version
@value{VERSION}, @value{UPDATED}
@menu
* About:: About Openocd.
......@@ -67,11 +72,11 @@ as numerous bugfixes and enhancements. See the AUTHORS file for regular contribu
You can download the current SVN version with SVN client of your choice from the
following repositories:
(@uref{svn://svn.berlios.de/openocd/trunk}
(@uref{svn://svn.berlios.de/openocd/trunk})
or
(@uref{http://svn.berlios.de/svnroot/repos/openocd/trunk}
(@uref{http://svn.berlios.de/svnroot/repos/openocd/trunk})
Using the SVN command line client, you could use the following command to fetch the
latest version (make sure there is no (non-svn) directory called "openocd" in the
......@@ -91,8 +96,8 @@ from the logs of one user - correct me if I'm wrong).
You further need the appropriate driver files, if you want to build support for
a FTDI FT2232 based interface:
@itemize @bullet
@item @b{ftdi2232} libftdi ((@uref{http://www.intra2net.com/opensource/ftdi/})
@item @b{ftd2xx} libftd2xx ((@uref{http://www.ftdichip.com/Drivers/D2XX.htm})
@item @b{ftdi2232} libftdi (@uref{http://www.intra2net.com/opensource/ftdi/})
@item @b{ftd2xx} libftd2xx (@uref{http://www.ftdichip.com/Drivers/D2XX.htm})
@item When using the Amontec JTAGkey, you have to get the drivers from the Amontec
homepage (@uref{www.amontec.com}), as the JTAGkey uses a non-standard VID/PID.
@end itemize
......@@ -142,7 +147,7 @@ build properly}
If you want to access the parallel port using the PPDEV interface you have to specify
both the @option{--enable-parport} AND the @option{--enable-parport_ppdev} option since
the @option{--enable-parport_ppdev} option actually is an option to the parport driver
(see (@uref{http://forum.sparkfun.com/viewtopic.php?t=3795} for more info).
(see @uref{http://forum.sparkfun.com/viewtopic.php?t=3795} for more info).
Cygwin users have to specify the location of the FTDI D2XX package. This should be an
absolute path containing no spaces.
......@@ -683,6 +688,7 @@ Dump <@var{size}> bytes of target memory starting at <@var{address}> to a
@item @b{verify_image} <@var{file}> <@var{address}> [@option{bin}|@option{ihex}|@option{elf}]
@cindex verify_image
Verify <@var{file}> to target memory starting at <@var{address}>.
This will first attempt using a crc checksum, if this fails it will try a binary compare.
@item @b{load_binary} <@var{file}> <@var{address}> [DEPRECATED]
@cindex load_binary
Load binary <@var{file}> to target memory at <@var{address}>
......@@ -714,12 +720,23 @@ updated information.
@item @b{flash protect_check} <@var{num}>
@cindex flash protect_check
Check protection state of sectors in flash bank <num>.
@item @b{flash erase} <@var{num}> <@var{first}> <@var{last}>
@item @b{flash erase} <@var{num}> <@var{first}> <@var{last}> [DEPRECATED]
@cindex flash erase
Erase sectors at bank <@var{num}>, starting at sector <@var{first}> up to and including
<@var{last}>. Sector numbering starts at 0. Depending on the flash type, erasing might
require the protection to be disabled first (e.g. Intel Advanced Bootblock flash using
the CFI driver).
the CFI driver). This command was replaced by the new command
@option{flash erase_sector} using the same syntax.
@item @b{flash erase_sector} <@var{num}> <@var{first}> <@var{last}>
@cindex flash erase_sector
Erase sectors at bank <@var{num}>, starting at sector <@var{first}> up to and including
<@var{last}>. Sector numbering starts at 0. Depending on the flash type, erasing might
require the protection to be disabled first (e.g. Intel Advanced Bootblock flash using
the CFI driver).
@item @b{flash erase_address} <@var{address}> <@var{length}>
@cindex flash erase_address
Erase sectors starting at <@var{address}> for <@var{length}> number of bytes
@item @b{flash write} <@var{num}> <@var{file}> <@var{offset}> [DEPRECATED]
@cindex flash write
Write the binary <@var{file}> to flash bank <@var{num}>, starting at <@var{offset}>
......@@ -1010,7 +1027,7 @@ Detailed information about each section can be found at OpenOCD configuration
@cindex OMAP5912 Flash Debug
The following two scripts was used with an wiggler PP and and a TI OMAP5912
dual core processor (@uref{http://www.ti.com}) on a OMAP5912 OSK board
@uref{(http://www.spectrumdigital.com}).
(@uref{http://www.spectrumdigital.com}).
@subsection Openocd config
@smallexample
#daemon configuration
......
......@@ -49,7 +49,6 @@ int handle_flash_erase_command(struct command_context_s *cmd_ctx, char *cmd, cha
int handle_flash_write_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_flash_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc);
flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr);
......@@ -117,8 +116,6 @@ int flash_init(struct command_context_s *cmd_ctx)
"write binary <bank> <file> <offset>");
register_command(cmd_ctx, flash_cmd, "write_image", handle_flash_write_image_command, COMMAND_EXEC,
"write_image <file> [offset] [type]");
register_command(cmd_ctx, flash_cmd, "verify_image", handle_flash_verify_image_command, COMMAND_EXEC,
"verify_image <file> [offset] [type]");
register_command(cmd_ctx, flash_cmd, "protect", handle_flash_protect_command, COMMAND_EXEC,
"set protection of sectors at <bank> <first> <last> <on|off>");
register_command(cmd_ctx, flash_cmd, "auto_erase", handle_flash_auto_erase_command, COMMAND_EXEC,
......@@ -364,69 +361,71 @@ int handle_flash_erase_check_command(struct command_context_s *cmd_ctx, char *cm
return ERROR_OK;
}
static void printError(struct command_context_s *cmd_ctx, flash_bank_t *p, int retval)
{
if (retval==ERROR_OK)
return;
switch (retval)
{
case ERROR_TARGET_NOT_HALTED:
command_print(cmd_ctx, "can't work with this flash while target is running");
break;
case ERROR_INVALID_ARGUMENTS:
command_print(cmd_ctx, "usage: flash write <bank> <file> <offset>");
break;
case ERROR_FLASH_BANK_INVALID:
command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base);
break;
case ERROR_FLASH_OPERATION_FAILED:
command_print(cmd_ctx, "flash program error");
break;
case ERROR_FLASH_DST_BREAKS_ALIGNMENT:
command_print(cmd_ctx, "offset breaks required alignment");
break;
case ERROR_FLASH_DST_OUT_OF_BANK:
command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)");
break;
case ERROR_FLASH_SECTOR_NOT_ERASED:
command_print(cmd_ctx, "destination sector(s) not erased");
break;
default:
command_print(cmd_ctx, "unknown error");
}
}
int handle_flash_erase_address_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
flash_bank_t *p;
int retval;
int address;
int length;
duration_t duration;
char *duration_text;
target_t *target = get_current_target(cmd_ctx);
if (argc != 2)
{
command_print(cmd_ctx, "usage: flash erase_address <address> <range>");
command_print(cmd_ctx, "usage: flash erase_address <address> <length>");
return ERROR_OK;
}
int address=strtoul(args[0], NULL, 0);
int length=strtoul(args[1], NULL, 0);
if (length<=0)
address = strtoul(args[0], NULL, 0);
length = strtoul(args[1], NULL, 0);
if (length <= 0)
{
command_print(cmd_ctx, "Length must be >0");
return ERROR_INVALID_ARGUMENTS;
}
p = get_flash_bank_by_addr(target, address);
if (p==NULL)
if (p == NULL)
{
command_print(cmd_ctx, "No flash at that address");
return ERROR_INVALID_ARGUMENTS;
}
int retval=flash_erase(target, address, length);
printError(cmd_ctx, p, retval);
return retval;
duration_start_measure(&duration);
if ((retval = flash_erase(target, address, length)) != ERROR_OK)
{
switch (retval)
{
case ERROR_TARGET_NOT_HALTED:
command_print(cmd_ctx, "can't work with this flash while target is running");
break;
case ERROR_INVALID_ARGUMENTS:
command_print(cmd_ctx, "usage: flash erase_address <address> <length>");
break;
case ERROR_FLASH_BANK_INVALID:
command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base);
break;
case ERROR_FLASH_OPERATION_FAILED:
command_print(cmd_ctx, "flash erase error");
break;
case ERROR_FLASH_SECTOR_INVALID:
command_print(cmd_ctx, "sector number(s) invalid");
break;
default:
command_print(cmd_ctx, "unknown error");
}
}
else
{
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "erased address 0x%8.8x length %i in %s", address, length, duration_text);
free(duration_text);
}
return retval;
}
int handle_flash_protect_check_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
......@@ -589,7 +588,7 @@ int handle_flash_protect_command(struct command_context_s *cmd_ctx, char *cmd, c
return ERROR_OK;
}
int handle_flash_write_image_command_core(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, enum flash_image_op op)
int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
target_t *target = get_current_target(cmd_ctx);
......@@ -641,17 +640,9 @@ int handle_flash_write_image_command_core(struct command_context_s *cmd_ctx, cha
failed = malloc(sizeof(int) * image.num_sections);
error_str=NULL;
retval=ERROR_OK;
if ((op==flash_image_op_write)&&auto_erase)
{
retval = flash_image_operation(target, &image, &written, &error_str, failed, flash_image_op_erase);
}
if (retval == ERROR_OK)
{
retval = flash_image_operation(target, &image, &written, &error_str, failed, op);
}
error_str = NULL;
retval = flash_write(target, &image, &written, &error_str, failed, auto_erase);
if (retval != ERROR_OK)
{
......@@ -675,11 +666,9 @@ int handle_flash_write_image_command_core(struct command_context_s *cmd_ctx, cha
}
duration_stop_measure(&duration, &duration_text);
command_print(cmd_ctx, "%s %u byte from file %s in %s (%f kb/s)",
(op==flash_image_op_write)?"wrote":"verified",
command_print(cmd_ctx, "wrote %u byte from file %s in %s (%f kb/s)",
written, args[0], duration_text,
(float)written / 1024.0 / ((float)duration.duration.tv_sec + ((float)duration.duration.tv_usec / 1000000.0)));
free(duration_text);
free(failed);
......@@ -688,16 +677,6 @@ int handle_flash_write_image_command_core(struct command_context_s *cmd_ctx, cha
return ERROR_OK;
}
int handle_flash_write_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
return handle_flash_write_image_command_core(cmd_ctx, cmd, args, argc, flash_image_op_write);
}
int handle_flash_verify_image_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
return handle_flash_write_image_command_core(cmd_ctx, cmd, args, argc, flash_image_op_verify);
}
int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc)
{
u32 offset;
......@@ -745,7 +724,33 @@ int handle_flash_write_binary_command(struct command_context_s *cmd_ctx, char *c
{
command_print(cmd_ctx, "failed writing file %s to flash bank %i at offset 0x%8.8x",
args[1], strtoul(args[0], NULL, 0), strtoul(args[2], NULL, 0));
printError(cmd_ctx, p, retval);
switch (retval)
{
case ERROR_TARGET_NOT_HALTED:
command_print(cmd_ctx, "can't work with this flash while target is running");
break;
case ERROR_INVALID_ARGUMENTS:
command_print(cmd_ctx, "usage: flash write <bank> <file> <offset>");
break;
case ERROR_FLASH_BANK_INVALID:
command_print(cmd_ctx, "no '%s' flash found at 0x%8.8x", p->driver->name, p->base);
break;
case ERROR_FLASH_OPERATION_FAILED:
command_print(cmd_ctx, "flash program error");
break;
case ERROR_FLASH_DST_BREAKS_ALIGNMENT:
command_print(cmd_ctx, "offset breaks required alignment");
break;
case ERROR_FLASH_DST_OUT_OF_BANK:
command_print(cmd_ctx, "destination is out of flash bank (offset and/or file too large)");
break;
case ERROR_FLASH_SECTOR_NOT_ERASED:
command_print(cmd_ctx, "destination sector(s) not erased");
break;
default:
command_print(cmd_ctx, "unknown error");
}
}
free(buffer);
......@@ -823,8 +828,8 @@ int flash_erase(target_t *target, u32 addr, u32 length)
return c->driver->erase(c, first, last);
}
/* perform an operation on flash using an image: verify, erase or write. */
int flash_image_operation(target_t *target, image_t *image, u32 *written, char **error_str, int *failed, enum flash_image_op op)
/* write (optional verify) an image to flash memory of the given target */
int flash_write(target_t *target, image_t *image, u32 *written, char **error_str, int *failed, int erase)
{
int retval;
int i;
......@@ -850,8 +855,8 @@ int flash_image_operation(target_t *target, image_t *image, u32 *written, char *
u8 *buffer;
int section_first;
int section_last;
u32 run_address = image->sections[section].base_address+section_offset;
u32 run_size = image->sections[section].size-section_offset;
u32 run_address = image->sections[section].base_address + section_offset;
u32 run_size = image->sections[section].size - section_offset;
if (image->sections[section].size == 0)
{
......@@ -943,57 +948,16 @@ int flash_image_operation(target_t *target, image_t *image, u32 *written, char *
retval = ERROR_OK;
switch (op)
if (erase)
{
case flash_image_op_erase:
/* calculate and erase sectors */
retval = flash_erase( target, run_address, run_size );
break;
case flash_image_op_write:
/* write flash sectors */
retval = c->driver->write(c, buffer, run_address - c->base, run_size);
break;
case flash_image_op_verify:
{
// Verify
u8 *data;
data=(u8 *)malloc(run_size);
if (data==NULL)
retval = ERROR_INVALID_ARGUMENTS; // exception handling would be nice...
// Can we use long word accesses?
int size=1;
int count=run_size;
if ((count%4)==0)
{
size*=4;
count/=4;
}
retval = target->type->read_memory(target, run_address, size, count, data);
/* calculate and erase sectors */
retval = flash_erase( target, run_address, run_size );
}
if (retval == ERROR_OK)
{
int i;
for (i=0; i<run_size; i++)
{
if (data[i]!=buffer[i])
{
ERROR("Verify operation failed address 0x%08x. Was %02x instead of %02x\n", i+run_address, data[i], buffer[i]);
retval=ERROR_FLASH_OPERATION_FAILED;
break;
}
}
}
free(data);
break;
}
default:
// can't happen
exit(-1);
if (retval == ERROR_OK)
{
/* write flash sectors */
retval = c->driver->write(c, buffer, run_address - c->base, run_size);
}
free(buffer);
......@@ -1053,6 +1017,3 @@ int handle_flash_auto_erase_command(struct command_context_s *cmd_ctx, char *cmd
return ERROR_OK;
}
......@@ -63,18 +63,11 @@ typedef struct flash_bank_s
struct flash_bank_s *next;
} flash_bank_t;
enum flash_image_op
{
flash_image_op_write = 0,
flash_image_op_verify,
flash_image_op_erase
};
extern int flash_register_commands(struct command_context_s *cmd_ctx);
extern int flash_init(struct command_context_s *cmd_ctx);
extern int flash_erase(target_t *target, u32 addr, u32 length);
extern int flash_image_operation(target_t *target, image_t *image, u32 *written, char **error_str, int *failed, enum flash_image_op op);
extern int flash_write(target_t *target, image_t *image, u32 *written, char **error, int *failed, int erase);
extern flash_bank_t *get_flash_bank_by_num(int num);
extern flash_bank_t *get_flash_bank_by_addr(target_t *target, u32 addr);
......
......@@ -44,8 +44,6 @@ int fileio_open_local(fileio_t *fileio)
fileio_local_t *fileio_local = malloc(sizeof(fileio_local_t));
char access[4];
fileio->location_private = fileio_local;
switch (fileio->access)
{
case FILEIO_READ:
......@@ -86,16 +84,18 @@ int fileio_open_local(fileio_t *fileio)
if ((fileio->access != FILEIO_WRITE) || (fileio->access == FILEIO_READWRITE))
{
// NB! Here we use fseek() instead of stat(), since stat is a
// more advanced operation that might not apply to e.g. a disk path
// that refers to e.g. a tftp client
int result=fseek(fileio_local->file, 0, SEEK_END);
/* NB! Here we use fseek() instead of stat(), since stat is a
* more advanced operation that might not apply to e.g. a disk path
* that refers to e.g. a tftp client */
int result, result2;
result = fseek(fileio_local->file, 0, SEEK_END);
fileio->size = ftell(fileio_local->file);
int result2 = fseek(fileio_local->file, 0, SEEK_SET);
result2 = fseek(fileio_local->file, 0, SEEK_SET);
if ((fileio->size<0)||(result<0)||(result2<0))
if ((fileio->size < 0) || (result < 0) || (result2 < 0))
{
fileio_close(fileio);
return ERROR_FILEIO_OPERATION_FAILED;
......@@ -106,6 +106,8 @@ int fileio_open_local(fileio_t *fileio)
fileio->size = 0x0;
}
fileio->location_private = fileio_local;
return ERROR_OK;
}
......
......@@ -1330,7 +1330,7 @@ int gdb_v_packet(connection_t *connection, target_t *target, char *packet, int p
char *error_str;
/* process the flashing buffer */
if ((result = flash_image_operation(gdb_service->target, gdb_connection->vflash_image, &written, &error_str, NULL, flash_image_op_write)) != ERROR_OK)
if ((result = flash_write(gdb_service->target, gdb_connection->vflash_image, &written, &error_str, NULL, 0)) != ERROR_OK)
{
if (result == ERROR_FLASH_DST_OUT_OF_BANK)
gdb_put_packet(connection, "E.memtype", 9);
......
......@@ -37,13 +37,13 @@
#include "target.h"
/* convert ELF header field to host endianness */
#define field16(elf,field)\
((elf->endianness==ELFDATA2LSB)? \
le_to_h_u16((u8*)&field):be_to_h_u16((u8*)&field))
#define field16(elf, field)\
((elf->endianness == ELFDATA2LSB)? \
le_to_h_u16((u8*)&field) : be_to_h_u16((u8*)&field))
#define field32(elf,field)\
((elf->endianness==ELFDATA2LSB)? \
le_to_h_u32((u8*)&field):be_to_h_u32((u8*)&field))
#define field32(elf, field)\
((elf->endianness == ELFDATA2LSB)? \
le_to_h_u32((u8*)&field) : be_to_h_u32((u8*)&field))
static int autodetect_image_type(image_t *image, char *url)
{
......@@ -79,15 +79,15 @@ static int autodetect_image_type(image_t *image, char *url)
DEBUG("ELF image detected.");
image->type = IMAGE_ELF;
}
else if ((buffer[0]==':') /* record start byte */
else if ((buffer[0] == ':') /* record start byte */
&&(isxdigit(buffer[1]))
&&(isxdigit(buffer[2]))
&&(isxdigit(buffer[3]))
&&(isxdigit(buffer[4]))
&&(isxdigit(buffer[5]))
&&(isxdigit(buffer[6]))
&&(buffer[7]=='0') /* record type : 00 -> 05 */
&&(buffer[8]>='0')&&(buffer[8]<'6'))
&&(buffer[7] == '0') /* record type : 00 -> 05 */
&&(buffer[8] >= '0') && (buffer[8] < '6'))
{
DEBUG("IHEX image detected.");
image->type = IMAGE_IHEX;
......@@ -402,12 +402,12 @@ int image_elf_read_headers(image_t *image)
/* count useful segments (loadable), ignore BSS section */
image->num_sections = 0;
for (i=0;i<elf->segment_count;i++)
for (i = 0; i < elf->segment_count; i++)
if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0))
image->num_sections++;
/* alloc and fill sections array with loadable segments */
image->sections = malloc(image->num_sections * sizeof(image_section_t));
for (i=0,j=0;i<elf->segment_count;i++)
for (i = 0, j = 0; i < elf->segment_count; i++)
{
if ((field32(elf, elf->segments[i].p_type) == PT_LOAD) && (field32(elf, elf->segments[i].p_filesz) != 0))
{
......@@ -429,22 +429,22 @@ int image_elf_read_section(image_t *image, int section, u32 offset, u32 size, u8
{
image_elf_t *elf = image->type_private;
Elf32_Phdr *segment = (Elf32_Phdr *)image->sections[section].private;
u32 read_size,really_read;
u32 read_size, really_read;
int retval;
*size_read = 0;
DEBUG("load segment %d at 0x%x (sz=0x%x)",section,offset,size);
DEBUG("load segment %d at 0x%x (sz = 0x%x)", section, offset, size);
/* read initialized data in current segment if any */
if (offset<field32(elf,segment->p_filesz))
if (offset < field32(elf, segment->p_filesz))
{
/* maximal size present in file for the current segment */
read_size = MIN(size, field32(elf,segment->p_filesz)-offset);
DEBUG("read elf: size = 0x%x at 0x%x",read_size,
field32(elf,segment->p_offset)+offset);
read_size = MIN(size, field32(elf, segment->p_filesz) - offset);
DEBUG("read elf: size = 0x%x at 0x%x", read_size,
field32(elf,segment->p_offset) + offset);
/* read initialized area of the segment */
if ((retval = fileio_seek(&elf->fileio, field32(elf,segment->p_offset)+offset)) != ERROR_OK)
if ((retval = fileio_seek(&elf->fileio, field32(elf,segment->p_offset) + offset)) != ERROR_OK)
{
ERROR("cannot find ELF segment content, seek failed");
return retval;
......@@ -463,12 +463,12 @@ int image_elf_read_section(image_t *image, int section, u32 offset, u32 size, u8
return ERROR_OK;
}
/* if there is remaining zeroed area in current segment */
if (offset<field32(elf,segment->p_memsz))
if (offset < field32(elf, segment->p_memsz))
{
/* fill zeroed part (BSS) of the segment */
read_size = MIN(size, field32(elf,segment->p_memsz)-offset);
DEBUG("zero fill: size = 0x%x",read_size);
memset(buffer,0,read_size);
read_size = MIN(size, field32(elf, segment->p_memsz) - offset);
DEBUG("zero fill: size = 0x%x", read_size);
memset(buffer, 0, read_size);
*size_read += read_size;
}
......@@ -561,7 +561,6 @@ int image_mot_buffer_complete(image_t *image)
bytes_read += 8;
count -=4;
break;
}
if (full_address != address)
......@@ -762,17 +761,17 @@ int image_open(image_t *image, char *url, char *type_string)
if (image->base_address_set)
{
// relocate
/* relocate */
int section;
for (section=0; section < image->num_sections; section++)
for (section = 0; section < image->num_sections; section++)
{
image->sections[section].base_address+=image->base_address;
image->sections[section].base_address += image->base_address;
}
// we're done relocating. The two statements below are mainly
// for documenation purposes: stop anyone from empirically
// thinking they should use these values henceforth.
image->base_address=0;
image->base_address_set=0;
/* we're done relocating. The two statements below are mainly
* for documenation purposes: stop anyone from empirically
* thinking they should use these values henceforth. */
image->base_address = 0;
image->base_address_set = 0;
}