Make more XFA element data truly read-only.

Split `g_ElementTable` into two, so some of it can move from
.data.rel.ro to .rodata.

.rodata: +2560
.data.rel.ro: -2560

Change-Id: I4b19685db410db0f0c471ba8aec1dfc83d7b4928
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/74736
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/xfa/fxfa/parser/xfa_basic_data.cpp b/xfa/fxfa/parser/xfa_basic_data.cpp
index 578b271..2579d2a 100644
--- a/xfa/fxfa/parser/xfa_basic_data.cpp
+++ b/xfa/fxfa/parser/xfa_basic_data.cpp
@@ -66,16 +66,27 @@
   uint32_t hash;  // Hashed as wide string.
   XFA_Element element;
   XFA_Element parent;
-  const char* name;
 };
 
-const ElementRecord g_ElementTable[] = {
+// Contains read-only data that do not require relocation.
+// Parts that require relocation are in `kElementNames` below.
+constexpr ElementRecord kElementRecords[] = {
 #undef ELEM____
-#define ELEM____(a, b, c, d) {a, XFA_Element::c, XFA_Element::d, b},
+#define ELEM____(a, b, c, d) {a, XFA_Element::c, XFA_Element::d},
 #include "xfa/fxfa/parser/elements.inc"
 #undef ELEM____
 };
 
+constexpr const char* kElementNames[] = {
+#undef ELEM____
+#define ELEM____(a, b, c, d) b,
+#include "xfa/fxfa/parser/elements.inc"
+#undef ELEM____
+};
+
+static_assert(pdfium::size(kElementRecords) == pdfium::size(kElementNames),
+              "Size mismatch");
+
 struct AttributeRecord {
   uint32_t hash;  // Hashed as wide string.
   XFA_Attribute attribute;
@@ -146,17 +157,20 @@
 }
 
 ByteStringView XFA_ElementToName(XFA_Element elem) {
-  return g_ElementTable[static_cast<size_t>(elem)].name;
+  return kElementNames[static_cast<size_t>(elem)];
 }
 
 XFA_Element XFA_GetElementByName(WideStringView name) {
   uint32_t hash = FX_HashCode_GetW(name, false);
   auto* elem = std::lower_bound(
-      std::begin(g_ElementTable), std::end(g_ElementTable), hash,
+      std::begin(kElementRecords), std::end(kElementRecords), hash,
       [](const ElementRecord& a, uint32_t hash) { return a.hash < hash; });
-  if (elem != std::end(g_ElementTable) && name.EqualsASCII(elem->name))
-    return elem->element;
-  return XFA_Element::Unknown;
+  if (elem == std::end(kElementRecords))
+    return XFA_Element::Unknown;
+
+  size_t index = std::distance(std::begin(kElementRecords), elem);
+  return name.EqualsASCII(kElementNames[index]) ? elem->element
+                                                : XFA_Element::Unknown;
 }
 
 ByteStringView XFA_AttributeToName(XFA_Attribute attr) {
@@ -218,7 +232,7 @@
       result.callback = kElementAttributeCallbacks[index];
       return result;
     }
-    element = g_ElementTable[static_cast<size_t>(element)].parent;
+    element = kElementRecords[static_cast<size_t>(element)].parent;
   }
   return {};
 }