+// Make a new symbol table entry.
+// STT_SPARC_REGISTER symbols require special handling,
+// so we intercept these symbols and keep track of them separately.
+// We will resolve register symbols here and output them at symbol
+// finalization time.
+
+template<int size, bool big_endian>
+Sized_symbol<size>*
+Target_sparc<size, big_endian>::make_symbol(const char* name,
+ elfcpp::STT type,
+ Object* object,
+ unsigned int shndx,
+ uint64_t value)
+{
+ // REGISTER symbols are used only on SPARC-64.
+ if (size == 64 && type == elfcpp::STT_SPARC_REGISTER)
+ {
+ // Ignore REGISTER symbols in dynamic objects.
+ if (object->is_dynamic())
+ return NULL;
+ // Only registers 2, 3, 6, and 7 can be declared global.
+ int reg = value;
+ switch (reg)
+ {
+ case 2: case 3:
+ reg -= 2;
+ break;
+ case 6: case 7:
+ reg -= 4;
+ break;
+ default:
+ gold_error(_("%s: only registers %%g[2367] can be declared "
+ "using STT_REGISTER"),
+ object->name().c_str());
+ return NULL;
+ }
+ Register_symbol& rsym = this->register_syms_[reg];
+ if (rsym.name == NULL)
+ {
+ rsym.name = name;
+ rsym.shndx = shndx;
+ rsym.obj = object;
+ }
+ else
+ {
+ if (strcmp(rsym.name, name) != 0)
+ {
+ gold_error(_("%s: register %%g%d declared as '%s'; "
+ "previously declared as '%s' in %s"),
+ object->name().c_str(),
+ static_cast<int>(value),
+ *name ? name : "#scratch",
+ *rsym.name ? rsym.name : "#scratch",
+ rsym.obj->name().c_str());
+ return NULL;
+ }
+ }
+ return NULL;
+ }
+ return new Sized_symbol<size>();
+}
+