diff --git a/src/main/scala/gtirb/GTIRBReadELF.scala b/src/main/scala/gtirb/GTIRBReadELF.scala index 7d313cd7c..fc09b5273 100644 --- a/src/main/scala/gtirb/GTIRBReadELF.scala +++ b/src/main/scala/gtirb/GTIRBReadELF.scala @@ -7,6 +7,7 @@ import translating.{ELFBind, ELFNDX, ELFSymType, ELFSymbol, ELFVis, ReadELFData} import util.Logger import java.io.ByteArrayInputStream +import scala.collection.mutable import scala.util.DynamicVariable import scala.util.chaining.scalaUtilChainingOps @@ -165,28 +166,45 @@ class GTIRBReadELF(protected val gtirb: GTIRBResolver) { (offs.toMap, exts.toSet) } - def getGlobals(): Set[SpecGlobal] = - gtirb.symbolEntriesByUuid.view.flatMap { - case (symid, (size, "OBJECT", "GLOBAL" | "LOCAL", "DEFAULT", idx)) => - - // val addr = symid.getReferentUuid.map(_.get.address) - val addr = symid.getReferentAddress - addr match { - case Some(addr) => - Some(SpecGlobal(symid.get.name, (size * 8).toInt, None, addr)) - - // if the referent is not a real block, then this is a - // forwarding target symbol. discard, because we generate - // the SpecGlobal from the forwarding source symbol. - case None => - assert( - gtirb.symbolForwardingInverse.contains(symid), - "a symbol with a referent that has no data block should be a forwarding target" - ) - None - } - case _ => None + def getGlobals(): Set[SpecGlobal] = { + val globals: List[SpecGlobal] = gtirb.symbolEntriesByUuid.view + .flatMap { + case (symid, (size, "OBJECT", "GLOBAL" | "LOCAL", "DEFAULT", idx)) => + + // val addr = symid.getReferentUuid.map(_.get.address) + val addr = symid.getReferentAddress + addr match { + case Some(addr) => + Some(SpecGlobal(symid.get.name, (size * 8).toInt, None, addr)) + + // if the referent is not a real block, then this is a + // forwarding target symbol. discard, because we generate + // the SpecGlobal from the forwarding source symbol. + case None => + assert( + gtirb.symbolForwardingInverse.contains(symid), + "a symbol with a referent that has no data block should be a forwarding target" + ) + None + } + case _ => None + } + .toList + .sortBy(_.address) + val symbolNames = mutable.Map[String, Int]() + globals.map { specGlobal => + val name = specGlobal.name + val newName = if (!symbolNames.contains(name)) { + symbolNames(name) = 1 + name + } else { + val symbolNameCount = symbolNames(name) + symbolNames(name) = symbolNameCount + 1 + s"$name#$symbolNameCount" + } + specGlobal.copy(name = newName) }.toSet + } def getFunctionEntries(): Set[FuncEntry] = gtirb.symbolEntriesByUuid.view.collect { diff --git a/src/main/scala/ir/IRLoading.scala b/src/main/scala/ir/IRLoading.scala index d523f024c..384df1b77 100644 --- a/src/main/scala/ir/IRLoading.scala +++ b/src/main/scala/ir/IRLoading.scala @@ -72,6 +72,9 @@ object IRLoading { val ReadELFData(symbols, externalFunctions, globals, funcEntries, globalOffsets, mainAddress) = relfData + // ensure globals have unique names + assert(globals.map(_.name).size == globals.size) + def continuation(ctx: IRContext) = val specification = IRLoading.loadSpecification(q.specFile, ctx.program, globals) IRContext(symbols, externalFunctions, globals, funcEntries, globalOffsets, specification, ctx.program) diff --git a/src/main/scala/translating/ReadELFLoader.scala b/src/main/scala/translating/ReadELFLoader.scala index 5d12b43bb..0ba6e95c3 100644 --- a/src/main/scala/translating/ReadELFLoader.scala +++ b/src/main/scala/translating/ReadELFLoader.scala @@ -7,6 +7,7 @@ import specification.* import util.{ILLoadingConfig, Logger} import scala.collection.immutable.{SortedMap, SortedSet} +import scala.collection.mutable import scala.jdk.CollectionConverters.* /** https://refspecs.linuxfoundation.org/elf/elf.pdf @@ -91,11 +92,21 @@ object ReadELFLoader { .toMap val mainAddress = ctx.symbolTable.asScala.flatMap(s => getFunctionAddress(s, config.mainProcedureName)) - val symbolTable = ctx.symbolTable.asScala.flatMap(s => visitSymbolTable(s)).toList - val globalVariables = symbolTable.collect { + val symbolNames = mutable.Map[String, Int]() + val symbolTable = ctx.symbolTable.asScala.flatMap(s => visitSymbolTable(s)).toList.sortBy(_.value) + val globalVariables = symbolTable.flatMap { case ELFSymbol(_, value, size, ELFSymType.OBJECT, ELFBind.GLOBAL | ELFBind.LOCAL, ELFVis.DEFAULT, ndx, name) if ndx != ELFNDX.UND => - SpecGlobal(name, size * 8, None, value) + val newName = if (!symbolNames.contains(name)) { + symbolNames(name) = 1 + name + } else { + val symbolNameCount = symbolNames(name) + symbolNames(name) = symbolNameCount + 1 + s"$name#$symbolNameCount" + } + Some(SpecGlobal(newName, size * 8, None, value)) + case _ => None }.toSet val functionEntries = symbolTable.collect {