#include "gold.h"
#include <cstdlib>
+#include <algorithm>
#include "merge.h"
// matter. We want to get consistent results across links so we
// don't use pointer comparison.
if (mk1.object != mk2.object)
- return mk1.object->name() < mk2.object->name();
+ {
+ // Two different object files can have the same name: if foo.a
+ // includes both bar/qux.o and baz/qux.o, then both end up with
+ // the name foo.a(qux.o). But it's impossible for two different
+ // object files to have both the same name and the same offset.
+ if (mk1.object->offset() != mk2.object->offset())
+ return mk1.object->offset() < mk2.object->offset();
+ return mk1.object->name() < mk2.object->name();
+ }
if (mk1.shndx != mk2.shndx)
return mk1.shndx < mk2.shndx;
return mk1.offset < mk2.offset;
// If MK is not in the map, lower_bound returns the next iterator
// larger than it.
- if (p->first.object != object
+ if (p == this->merge_map_.end()
+ || p->first.object != object
|| p->first.shndx != shndx
|| p->first.offset != offset)
{
Output_merge_data::add_constant(const unsigned char* p)
{
uint64_t entsize = this->entsize();
- if (this->len_ + entsize > this->alc_)
+ uint64_t addsize = std::max(entsize, this->addralign());
+ if (this->len_ + addsize > this->alc_)
{
if (this->alc_ == 0)
- this->alc_ = 128 * entsize;
+ this->alc_ = 128 * addsize;
else
this->alc_ *= 2;
this->p_ = static_cast<unsigned char*>(realloc(this->p_, this->alc_));
if (this->p_ == NULL)
- gold_fatal("out of memory", true);
+ gold_nomem();
}
memcpy(this->p_ + this->len_, p, entsize);
- this->len_ += entsize;
+ if (addsize > entsize)
+ memset(this->p_ + this->len_ + entsize, 0, addsize - entsize);
+ this->len_ += addsize;
}
// Add the input section SHNDX in OBJECT to a merged output section
Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
{
off_t len;
- const unsigned char* p = object->section_contents(shndx, &len);
+ const unsigned char* p = object->section_contents(shndx, &len, false);
uint64_t entsize = this->entsize();
unsigned int shndx)
{
off_t len;
- const unsigned char* pdata = object->section_contents(shndx, &len);
+ const unsigned char* pdata = object->section_contents(shndx, &len, false);
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
if (len % sizeof(Char_type) != 0)
{
- fprintf(stderr,
- _("%s: %s: mergeable string section length not multiple of "
- "character size\n"),
- program_name, object->name().c_str());
- gold_exit(false);
+ object->error(_("mergeable string section length not multiple of "
+ "character size"));
+ return false;
}
- len /= sizeof(Char_type);
+ // The index I is in bytes, not characters.
off_t i = 0;
while (i < len)
{
off_t plen = 0;
for (const Char_type* pl = p; *pl != 0; ++pl)
{
+ // The length PLEN is in characters, not bytes.
++plen;
- if (i + plen >= len)
+ if (i + plen * static_cast<off_t>(sizeof(Char_type)) >= len)
{
- fprintf(stderr,
- _("%s: %s: entry in mergeable string section "
- "not null terminated\n"),
- program_name, object->name().c_str());
- gold_exit(false);
+ object->error(_("entry in mergeable string section "
+ "not null terminated"));
+ break;
}
}
- const Char_type* str = this->stringpool_.add(p, NULL);
+ const Char_type* str = this->stringpool_.add(p, true, NULL);
this->merged_strings_.push_back(Merged_string(object, shndx, i, str));
p += plen + 1;
- i += plen + 1;
+ i += (plen + 1) * sizeof(Char_type);
}
return true;