diff --git a/gdb/ada-exp.y b/gdb/ada-exp.y
index 0a49952..c02f6a1 100644
--- a/gdb/ada-exp.y
+++ b/gdb/ada-exp.y
@@ -1086,9 +1086,9 @@ static struct type*
 find_primitive_type (struct parser_state *par_state, char *name)
 {
   struct type *type;
-  type = language_lookup_primitive_type_by_name (parse_language (par_state),
-						 parse_gdbarch (par_state),
-						 name);
+  type = language_lookup_primitive_type (parse_language (par_state),
+					 parse_gdbarch (par_state),
+					 name);
   if (type == NULL && strcmp ("system__address", name) == 0)
     type = type_system_address (par_state);
 
@@ -1525,9 +1525,9 @@ static struct type *
 type_system_address (struct parser_state *par_state)
 {
   struct type *type 
-    = language_lookup_primitive_type_by_name (parse_language (par_state),
-					      parse_gdbarch (par_state),
-					      "system__address");
+    = language_lookup_primitive_type (parse_language (par_state),
+				      parse_gdbarch (par_state),
+				      "system__address");
   return  type != NULL ? type : parse_type (par_state)->builtin_data_ptr;
 }
 
diff --git a/gdb/ada-lang.c b/gdb/ada-lang.c
index 3a024d9..a017c84 100644
--- a/gdb/ada-lang.c
+++ b/gdb/ada-lang.c
@@ -3718,7 +3718,10 @@ See set/show multiple-symbol."));
             (SYMBOL_CLASS (syms[i].sym) == LOC_CONST
              && SYMBOL_TYPE (syms[i].sym) != NULL
              && TYPE_CODE (SYMBOL_TYPE (syms[i].sym)) == TYPE_CODE_ENUM);
-          struct symtab *symtab = SYMBOL_SYMTAB (syms[i].sym);
+	  struct symtab *symtab = NULL;
+
+	  if (!SYMBOL_IS_ARCH_OWNED (syms[i].sym))
+	    symtab = symbol_symtab (syms[i].sym);
 
           if (SYMBOL_LINE (syms[i].sym) != 0 && symtab != NULL)
             printf_unfiltered (_("[%d] %s at %s:%d\n"),
@@ -4468,14 +4471,19 @@ cache_symbol (const char *name, domain_enum namespace, struct symbol *sym,
   char *copy;
   struct cache_entry *e;
 
+  /* Symbols for builtin types don't have a block.
+     For now don't cache such symbols.  */
+  if (sym != NULL && SYMBOL_IS_ARCH_OWNED (sym))
+    return;
+
   /* If the symbol is a local symbol, then do not cache it, as a search
      for that symbol depends on the context.  To determine whether
      the symbol is local or not, we check the block where we found it
      against the global and static blocks of its associated symtab.  */
   if (sym
-      && BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (sym->symtab),
+      && BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symbol_symtab (sym)),
 			    GLOBAL_BLOCK) != block
-      && BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (sym->symtab),
+      && BLOCKVECTOR_BLOCK (SYMTAB_BLOCKVECTOR (symbol_symtab (sym)),
 			    STATIC_BLOCK) != block)
     return;
 
@@ -5587,14 +5595,17 @@ ada_lookup_symbol (const char *name, const struct block *block0,
 }
 
 static struct symbol *
-ada_lookup_symbol_nonlocal (const char *name,
+ada_lookup_symbol_nonlocal (const struct language_defn *langdef,
+			    const char *name,
                             const struct block *block,
                             const domain_enum domain)
 {
+  /* FIXME(dje): Do we need to consider builtin types here.
+     See basic_lookup_symbol_nonlocal for an example.  */
+
   return ada_lookup_symbol (name, block_static_block (block), domain, NULL);
 }
 
-
 /* True iff STR is a possible encoded suffix of a normal Ada name
    that is to be ignored for matching purposes.  Suffixes of parallel
    names (e.g., XVE) are not included here.  Currently, the possible suffixes
diff --git a/gdb/block.c b/gdb/block.c
index e791c73..8d45b6e 100644
--- a/gdb/block.c
+++ b/gdb/block.c
@@ -25,6 +25,7 @@
 #include "cp-support.h"
 #include "addrmap.h"
 #include "gdbtypes.h"
+#include "objfiles.h"
 
 /* This is used by struct block to store namespace-related info for
    C++ files, namely using declarations and the current namespace in
@@ -39,6 +40,31 @@ struct block_namespace_info
 static void block_initialize_namespace (struct block *block,
 					struct obstack *obstack);
 
+/* See block.h.  */
+
+struct objfile *
+block_objfile (const struct block *block)
+{
+  const struct global_block *global_block;
+
+  if (BLOCK_FUNCTION (block) != NULL)
+    return symbol_objfile (BLOCK_FUNCTION (block));
+
+  global_block = (struct global_block *) block_global_block (block);
+  return COMPUNIT_OBJFILE (global_block->compunit_symtab);
+}
+
+/* See block.  */
+
+struct gdbarch *
+block_gdbarch (const struct block *block)
+{
+  if (BLOCK_FUNCTION (block) != NULL)
+    return symbol_arch (BLOCK_FUNCTION (block));
+
+  return get_objfile_arch (block_objfile (block));
+}
+
 /* Return Nonzero if block a is lexically nested within block b,
    or if a and b have the same pc range.
    Return zero otherwise.  */
diff --git a/gdb/block.h b/gdb/block.h
index 409a5c7..e6c5feb 100644
--- a/gdb/block.h
+++ b/gdb/block.h
@@ -136,6 +136,14 @@ struct blockvector
 #define BLOCKVECTOR_BLOCK(blocklist,n) (blocklist)->block[n]
 #define BLOCKVECTOR_MAP(blocklist) ((blocklist)->map)
 
+/* Return the objfile of BLOCK, which must be non-NULL.  */
+
+extern struct objfile *block_objfile (const struct block *block);
+
+/* Return the architecture of BLOCK, which must be non-NULL.  */
+
+extern struct gdbarch *block_gdbarch (const struct block *block);
+
 extern struct symbol *block_linkage_function (const struct block *);
 
 extern struct symbol *block_containing_function (const struct block *);
diff --git a/gdb/btrace.c b/gdb/btrace.c
index b8b5139..b8e2fab 100644
--- a/gdb/btrace.c
+++ b/gdb/btrace.c
@@ -79,7 +79,7 @@ ftrace_print_filename (const struct btrace_function *bfun)
   sym = bfun->sym;
 
   if (sym != NULL)
-    filename = symtab_to_filename_for_display (sym->symtab);
+    filename = symtab_to_filename_for_display (symbol_symtab (sym));
   else
     filename = "<unknown>";
 
@@ -151,8 +151,8 @@ ftrace_function_switched (const struct btrace_function *bfun,
 	return 1;
 
       /* Check the location of those functions, as well.  */
-      bfname = symtab_to_fullname (sym->symtab);
-      fname = symtab_to_fullname (fun->symtab);
+      bfname = symtab_to_fullname (symbol_symtab (sym));
+      fname = symtab_to_fullname (symbol_symtab (fun));
       if (filename_cmp (fname, bfname) != 0)
 	return 1;
     }
@@ -183,7 +183,7 @@ ftrace_skip_file (const struct btrace_function *bfun, const char *fullname)
   if (sym == NULL)
     return 1;
 
-  bfile = symtab_to_fullname (sym->symtab);
+  bfile = symtab_to_fullname (symbol_symtab (sym));
 
   return (filename_cmp (bfile, fullname) != 0);
 }
diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index 163dd47..d3192cf 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -1477,15 +1477,15 @@ end_symtab_with_blockvector (struct block *static_block,
 	/* Inlined functions may have symbols not in the global or
 	   static symbol lists.  */
 	if (BLOCK_FUNCTION (block) != NULL)
-	  if (SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) == NULL)
-	    SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) = symtab;
+	  if (symbol_symtab (BLOCK_FUNCTION (block)) == NULL)
+	    symbol_set_symtab (BLOCK_FUNCTION (block), symtab);
 
 	/* Note that we only want to fix up symbols from the local
 	   blocks, not blocks coming from included symtabs.  That is why
 	   we use ALL_DICT_SYMBOLS here and not ALL_BLOCK_SYMBOLS.  */
 	ALL_DICT_SYMBOLS (BLOCK_DICT (block), iter, sym)
-	  if (SYMBOL_SYMTAB (sym) == NULL)
-	    SYMBOL_SYMTAB (sym) = symtab;
+	  if (symbol_symtab (sym) == NULL)
+	    symbol_set_symtab (sym, symtab);
       }
   }
 
@@ -1578,8 +1578,8 @@ set_missing_symtab (struct pending *pending_list,
     {
       for (i = 0; i < pending->nsyms; ++i)
 	{
-	  if (SYMBOL_SYMTAB (pending->symbol[i]) == NULL)
-	    SYMBOL_SYMTAB (pending->symbol[i]) = COMPUNIT_FILETABS (cu);
+	  if (symbol_symtab (pending->symbol[i]) == NULL)
+	    symbol_set_symtab (pending->symbol[i], COMPUNIT_FILETABS (cu));
 	}
     }
 }
diff --git a/gdb/c-exp.y b/gdb/c-exp.y
index 9d1c4c7..91728ee 100644
--- a/gdb/c-exp.y
+++ b/gdb/c-exp.y
@@ -2941,13 +2941,6 @@ classify_name (struct parser_state *par_state, const struct block *block,
       return TYPENAME;
     }
 
-  yylval.tsym.type
-    = language_lookup_primitive_type_by_name (parse_language (par_state),
-					      parse_gdbarch (par_state),
-					      copy);
-  if (yylval.tsym.type != NULL)
-    return TYPENAME;
-
   /* See if it's an ObjC classname.  */
   if (parse_language (par_state)->la_language == language_objc && !sym)
     {
diff --git a/gdb/cp-namespace.c b/gdb/cp-namespace.c
index 2877f73..550be29 100644
--- a/gdb/cp-namespace.c
+++ b/gdb/cp-namespace.c
@@ -221,20 +221,23 @@ cp_has_anonymous (const char *symbol_name)
    DOMAIN says what kind of symbols we're looking for.  */
 
 struct symbol *
-cp_lookup_symbol_nonlocal (const char *name,
+cp_lookup_symbol_nonlocal (const struct language_defn *langdef,
+			   const char *name,
 			   const struct block *block,
 			   const domain_enum domain)
 {
   struct symbol *sym;
   const char *scope = block_scope (block);
 
-  sym = lookup_namespace_scope (name, block,
-				domain, scope, 0);
+  /* FIXME(dje): Need to consider builtin types here, but we first need to
+     untangle all the various namespace/scope lookup routines.
+     See basic_lookup_symbol_nonlocal for an example.  */
+
+  sym = lookup_namespace_scope (name, block, domain, scope, 0);
   if (sym != NULL)
     return sym;
 
-  return cp_lookup_symbol_namespace (scope, name,
-				     block, domain);
+  return cp_lookup_symbol_namespace (scope, name, block, domain);
 }
 
 /* Look up NAME in the C++ namespace NAMESPACE.  Other arguments are
@@ -470,8 +473,7 @@ cp_lookup_symbol_imports_or_template (const char *scope,
 	  char *name_copy = xstrdup (SYMBOL_NATURAL_NAME (function));
 	  struct cleanup *cleanups = make_cleanup (xfree, name_copy);
 	  const struct language_defn *lang = language_def (language_cplus);
-	  struct gdbarch *arch
-	    = get_objfile_arch (SYMBOL_OBJFILE (function));
+	  struct gdbarch *arch = symbol_arch (function);
 	  const struct block *parent = BLOCK_SUPERBLOCK (block);
 
 	  while (1)
diff --git a/gdb/cp-support.h b/gdb/cp-support.h
index 74da3eb..c937186 100644
--- a/gdb/cp-support.h
+++ b/gdb/cp-support.h
@@ -192,9 +192,11 @@ extern void cp_add_using_directive (const char *dest,
 extern void cp_scan_for_anonymous_namespaces (const struct symbol *symbol,
 					      struct objfile *objfile);
 
-extern struct symbol *cp_lookup_symbol_nonlocal (const char *name,
-						 const struct block *block,
-						 const domain_enum domain);
+extern struct symbol *cp_lookup_symbol_nonlocal
+     (const struct language_defn *langdef,
+      const char *name,
+      const struct block *block,
+      const domain_enum domain);
 
 extern struct symbol *cp_lookup_symbol_namespace (const char *namespace,
 						  const char *name,
diff --git a/gdb/d-exp.y b/gdb/d-exp.y
index 5e4c10d..00d3a26 100644
--- a/gdb/d-exp.y
+++ b/gdb/d-exp.y
@@ -1577,8 +1577,8 @@ yylex (void)
     return DOLLAR_VARIABLE;
 
   yylval.tsym.type
-    = language_lookup_primitive_type_by_name (parse_language (pstate),
-					      parse_gdbarch (pstate), copy);
+    = language_lookup_primitive_type (parse_language (pstate),
+				      parse_gdbarch (pstate), copy);
   if (yylval.tsym.type != NULL)
     return TYPENAME;
 
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 2b2d820..61d2543 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -7735,8 +7735,9 @@ fixup_go_packaging (struct dwarf2_cu *cu)
 		  if (strcmp (package_name, this_package_name) != 0)
 		    complaint (&symfile_complaints,
 			       _("Symtab %s has objects from two different Go packages: %s and %s"),
-			       (SYMBOL_SYMTAB (sym)
-			  ? symtab_to_filename_for_display (SYMBOL_SYMTAB (sym))
+			       (symbol_symtab (sym) != NULL
+				? symtab_to_filename_for_display (
+				    symbol_symtab (sym))
 				: objfile_name (cu->objfile)),
 			       this_package_name, package_name);
 		  xfree (this_package_name);
@@ -17881,7 +17882,7 @@ new_symbol_full (struct die_info *die, struct type *type, struct dwarf2_cu *cu,
 	      struct file_entry *fe;
 
 	      fe = &cu->line_header->file_names[file_index - 1];
-	      SYMBOL_SYMTAB (sym) = fe->symtab;
+	      symbol_set_symtab (sym, fe->symtab);
 	    }
 	}
 
diff --git a/gdb/f-exp.y b/gdb/f-exp.y
index f229afa..ab3801a 100644
--- a/gdb/f-exp.y
+++ b/gdb/f-exp.y
@@ -1230,8 +1230,8 @@ yylex (void)
       }
 
     yylval.tsym.type
-      = language_lookup_primitive_type_by_name (parse_language (pstate),
-						parse_gdbarch (pstate), tmp);
+      = language_lookup_primitive_type (parse_language (pstate),
+					parse_gdbarch (pstate), tmp);
     if (yylval.tsym.type != NULL)
       return TYPENAME;
     
diff --git a/gdb/findvar.c b/gdb/findvar.c
index 512c572..d2adec4 100644
--- a/gdb/findvar.c
+++ b/gdb/findvar.c
@@ -455,7 +455,7 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
 	{
 	  CORE_ADDR addr
 	    = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
-					SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (var),
+					SYMBOL_OBJ_SECTION (symbol_objfile (var),
 							    var));
 
 	  store_typed_address (value_contents_raw (v), type, addr);
@@ -481,7 +481,7 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
     case LOC_STATIC:
       if (overlay_debugging)
 	addr = symbol_overlayed_address (SYMBOL_VALUE_ADDRESS (var),
-					 SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (var),
+					 SYMBOL_OBJ_SECTION (symbol_objfile (var),
 							     var));
       else
 	addr = SYMBOL_VALUE_ADDRESS (var);
@@ -523,8 +523,8 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
     case LOC_BLOCK:
       if (overlay_debugging)
 	addr = symbol_overlayed_address
-	  (BLOCK_START (SYMBOL_BLOCK_VALUE (var)), SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (var),
-								       var));
+	  (BLOCK_START (SYMBOL_BLOCK_VALUE (var)),
+	   SYMBOL_OBJ_SECTION (symbol_objfile (var), var));
       else
 	addr = BLOCK_START (SYMBOL_BLOCK_VALUE (var));
       break;
@@ -573,9 +573,9 @@ default_read_var_value (struct symbol *var, struct frame_info *frame)
 	lookup_data.name = SYMBOL_LINKAGE_NAME (var);
 
 	gdbarch_iterate_over_objfiles_in_search_order
-	  (get_objfile_arch (SYMBOL_OBJFILE (var)),
+	  (symbol_arch (var),
 	   minsym_lookup_iterator_cb, &lookup_data,
-	   SYMBOL_OBJFILE (var));
+	   symbol_objfile (var));
 	msym = lookup_data.result.minsym;
 
 	if (msym == NULL)
diff --git a/gdb/frame.c b/gdb/frame.c
index 75ad341..54aff59 100644
--- a/gdb/frame.c
+++ b/gdb/frame.c
@@ -2346,7 +2346,7 @@ find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
       init_sal (sal);
       if (SYMBOL_LINE (sym) != 0)
 	{
-	  sal->symtab = SYMBOL_SYMTAB (sym);
+	  sal->symtab = symbol_symtab (sym);
 	  sal->line = SYMBOL_LINE (sym);
 	}
       else
diff --git a/gdb/gdbtypes.c b/gdb/gdbtypes.c
index 611a0e7..553ae7e 100644
--- a/gdb/gdbtypes.c
+++ b/gdb/gdbtypes.c
@@ -1293,14 +1293,11 @@ lookup_typename (const struct language_defn *language,
   struct symbol *sym;
   struct type *type;
 
-  sym = lookup_symbol (name, block, VAR_DOMAIN, 0);
+  sym = lookup_symbol_in_language (name, block, VAR_DOMAIN,
+				   language->la_language, NULL);
   if (sym != NULL && SYMBOL_CLASS (sym) == LOC_TYPEDEF)
     return SYMBOL_TYPE (sym);
 
-  type = language_lookup_primitive_type_by_name (language, gdbarch, name);
-  if (type)
-    return type;
-
   if (noerr)
     return NULL;
   error (_("No type named %s."), name);
diff --git a/gdb/go-exp.y b/gdb/go-exp.y
index f9ffbf9..5178178 100644
--- a/gdb/go-exp.y
+++ b/gdb/go-exp.y
@@ -1455,9 +1455,9 @@ classify_name (struct parser_state *par_state, const struct block *block)
   copy = copy_name (yylval.sval);
 
   /* Try primitive types first so they win over bad/weird debug info.  */
-  type = language_lookup_primitive_type_by_name (parse_language (par_state),
-						 parse_gdbarch (par_state),
-						 copy);
+  type = language_lookup_primitive_type (parse_language (par_state),
+					 parse_gdbarch (par_state),
+					 copy);
   if (type != NULL)
     {
       /* NOTE: We take advantage of the fact that yylval coming in was a
diff --git a/gdb/guile/scm-frame.c b/gdb/guile/scm-frame.c
index b2d662e..70572ab 100644
--- a/gdb/guile/scm-frame.c
+++ b/gdb/guile/scm-frame.c
@@ -608,11 +608,8 @@ gdbscm_frame_block (SCM self)
 
   if (block != NULL)
     {
-      struct symtab *st;
-      SCM block_scm;
-
-      st = SYMBOL_SYMTAB (BLOCK_FUNCTION (fn_block));
-      return bkscm_scm_from_block (block, SYMTAB_OBJFILE (st));
+      return bkscm_scm_from_block
+	(block, symbol_objfile (BLOCK_FUNCTION (fn_block)));
     }
 
   return SCM_BOOL_F;
diff --git a/gdb/guile/scm-symbol.c b/gdb/guile/scm-symbol.c
index d80aa54..0a5a22e 100644
--- a/gdb/guile/scm-symbol.c
+++ b/gdb/guile/scm-symbol.c
@@ -50,6 +50,13 @@ static SCM domain_keyword;
 static SCM frame_keyword;
 
 static const struct objfile_data *syscm_objfile_data_key;
+static struct gdbarch_data *syscm_gdbarch_data_key;
+
+struct syscm_gdbarch_data
+{
+  /* Hash table to implement eqable gdbarch symbols.  */
+  htab_t htab;
+};
 
 /* Administrivia for symbol smobs.  */
 
@@ -75,20 +82,44 @@ syscm_eq_symbol_smob (const void *ap, const void *bp)
 	  && a->symbol != NULL);
 }
 
+static void *
+syscm_init_arch_symbols (struct gdbarch *gdbarch)
+{
+  struct syscm_gdbarch_data *data
+    = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct syscm_gdbarch_data);
+
+  data->htab = gdbscm_create_eqable_gsmob_ptr_map (syscm_hash_symbol_smob,
+						   syscm_eq_symbol_smob);
+  return data;
+}
+
 /* Return the struct symbol pointer -> SCM mapping table.
    It is created if necessary.  */
 
 static htab_t
-syscm_objfile_symbol_map (struct symbol *symbol)
+syscm_get_symbol_map (struct symbol *symbol)
 {
-  struct objfile *objfile = SYMBOL_OBJFILE (symbol);
-  htab_t htab = objfile_data (objfile, syscm_objfile_data_key);
+  htab_t htab;
 
-  if (htab == NULL)
+  if (SYMBOL_IS_ARCH_OWNED (symbol))
     {
-      htab = gdbscm_create_eqable_gsmob_ptr_map (syscm_hash_symbol_smob,
-						 syscm_eq_symbol_smob);
-      set_objfile_data (objfile, syscm_objfile_data_key, htab);
+      struct gdbarch *gdbarch = symbol_arch (symbol);
+      struct syscm_gdbarch_data *data = gdbarch_data (gdbarch,
+						      syscm_gdbarch_data_key);
+
+      htab = data->htab;
+    }
+  else
+    {
+      struct objfile *objfile = symbol_objfile (symbol);
+
+      htab = objfile_data (objfile, syscm_objfile_data_key);
+      if (htab == NULL)
+	{
+	  htab = gdbscm_create_eqable_gsmob_ptr_map (syscm_hash_symbol_smob,
+						     syscm_eq_symbol_smob);
+	  set_objfile_data (objfile, syscm_objfile_data_key, htab);
+	}
     }
 
   return htab;
@@ -103,7 +134,7 @@ syscm_free_symbol_smob (SCM self)
 
   if (s_smob->symbol != NULL)
     {
-      htab_t htab = syscm_objfile_symbol_map (s_smob->symbol);
+      htab_t htab = syscm_get_symbol_map (s_smob->symbol);
 
       gdbscm_clear_eqable_gsmob_ptr_slot (htab, &s_smob->base);
     }
@@ -181,7 +212,7 @@ syscm_scm_from_symbol (struct symbol *symbol)
 
   /* If we've already created a gsmob for this symbol, return it.
      This makes symbols eq?-able.  */
-  htab = syscm_objfile_symbol_map (symbol);
+  htab = syscm_get_symbol_map (symbol);
   s_smob_for_lookup.symbol = symbol;
   slot = gdbscm_find_eqable_gsmob_ptr_slot (htab, &s_smob_for_lookup.base);
   if (*slot != NULL)
@@ -319,8 +350,9 @@ gdbscm_symbol_type (SCM self)
   return tyscm_scm_from_type (SYMBOL_TYPE (symbol));
 }
 
-/* (symbol-symtab <gdb:symbol>) -> <gdb:symtab>
-   Return the symbol table of SELF.  */
+/* (symbol-symtab <gdb:symbol>) -> <gdb:symtab> | #f
+   Return the symbol table of SELF.
+   If SELF does not have a symtab (it is arch-owned) return #f.  */
 
 static SCM
 gdbscm_symbol_symtab (SCM self)
@@ -329,7 +361,9 @@ gdbscm_symbol_symtab (SCM self)
     = syscm_get_valid_symbol_smob_arg_unsafe (self, SCM_ARG1, FUNC_NAME);
   const struct symbol *symbol = s_smob->symbol;
 
-  return stscm_scm_from_symtab (SYMBOL_SYMTAB (symbol));
+  if (SYMBOL_IS_ARCH_OWNED (symbol))
+    return SCM_BOOL_F;
+  return stscm_scm_from_symtab (symbol_symtab (symbol));
 }
 
 /* (symbol-name <gdb:symbol>) -> string */
@@ -761,4 +795,8 @@ gdbscm_initialize_symbols (void)
      invalidate symbols when an object file is about to be deleted.  */
   syscm_objfile_data_key
     = register_objfile_data_with_cleanup (NULL, syscm_del_objfile_symbols);
+
+  /* Arch-specific symbol data.  */
+  syscm_gdbarch_data_key
+    = gdbarch_data_register_post_init (syscm_init_arch_symbols);
 }
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index 4415b31..0e1b736 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1199,9 +1199,12 @@ jump_command (char *arg, int from_tty)
 
   if (sfn != NULL)
     {
+      struct obj_section *section;
+
       fixup_symbol_section (sfn, 0);
-      if (section_is_overlay (SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sfn), sfn)) &&
-	  !section_is_mapped (SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sfn), sfn)))
+      section = SYMBOL_OBJ_SECTION (symbol_objfile (sfn), sfn);
+      if (section_is_overlay (section)
+	  && !section_is_mapped (section))
 	{
 	  if (!query (_("WARNING!!!  Destination is in "
 			"unmapped overlay!  Jump anyway? ")))
diff --git a/gdb/jit.c b/gdb/jit.c
index 1e42ce2..8d3290a 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -697,7 +697,7 @@ finalize_symtab (struct gdb_symtab *stab, struct objfile *objfile)
       /* The name.  */
       SYMBOL_DOMAIN (block_name) = VAR_DOMAIN;
       SYMBOL_ACLASS_INDEX (block_name) = LOC_BLOCK;
-      SYMBOL_SYMTAB (block_name) = COMPUNIT_FILETABS (cust);
+      symbol_set_symtab (block_name, COMPUNIT_FILETABS (cust));
       SYMBOL_TYPE (block_name) = lookup_function_type (block_type);
       SYMBOL_BLOCK_VALUE (block_name) = new_block;
 
diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
index acc191a..05dd0fa 100644
--- a/gdb/jv-lang.c
+++ b/gdb/jv-lang.c
@@ -174,8 +174,7 @@ get_java_class_symtab (struct gdbarch *gdbarch)
 static void
 add_class_symtab_symbol (struct symbol *sym)
 {
-  struct compunit_symtab *cust
-    = get_java_class_symtab (get_objfile_arch (SYMBOL_OBJFILE (sym)));
+  struct compunit_symtab *cust = get_java_class_symtab (symbol_arch (sym));
   const struct blockvector *bv = COMPUNIT_BLOCKVECTOR (cust);
 
   dict_add_symbol (BLOCK_DICT (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK)), sym);
diff --git a/gdb/language.c b/gdb/language.c
index 034086d1..d5ed916 100644
--- a/gdb/language.c
+++ b/gdb/language.c
@@ -981,23 +981,121 @@ language_bool_type (const struct language_defn *la,
   return ld->arch_info[la->la_language].bool_type_default;
 }
 
+/* Helper function for primitive type lookup.  */
+
+static struct type **
+language_lookup_primitive_type_1 (const struct language_arch_info *lai,
+				  const char *name)
+{
+  struct type **p;
+
+  for (p = lai->primitive_type_vector; (*p) != NULL; p++)
+    {
+      if (strcmp (TYPE_NAME (*p), name) == 0)
+	return p;
+    }
+  return NULL;
+}
+
+/* See language.h.  */
+
 struct type *
-language_lookup_primitive_type_by_name (const struct language_defn *la,
-					struct gdbarch *gdbarch,
-					const char *name)
+language_lookup_primitive_type (const struct language_defn *la,
+				struct gdbarch *gdbarch,
+				const char *name)
 {
   struct language_gdbarch *ld = gdbarch_data (gdbarch,
 					      language_gdbarch_data);
-  struct type *const *p;
+  struct type **typep;
+
+  typep = language_lookup_primitive_type_1 (&ld->arch_info[la->la_language],
+					    name);
+  if (typep == NULL)
+    return NULL;
+  return *typep;
+}
+
+/* Helper function for type lookup as a symbol.
+   Create the symbol corresponding to type TYPE in language LANG.  */
+
+static struct symbol *
+language_alloc_type_symbol (enum language lang, struct type *type)
+{
+  struct symbol *symbol;
+  struct gdbarch *gdbarch;
+
+  gdb_assert (!TYPE_OBJFILE_OWNED (type));
+
+  gdbarch = TYPE_OWNER (type).gdbarch;
+  symbol = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct symbol);
+
+  symbol->ginfo.name = TYPE_NAME (type);
+  symbol->ginfo.language = lang;
+  symbol->owner.arch = gdbarch;
+  SYMBOL_IS_ARCH_OWNED (symbol) = 1;
+  SYMBOL_TYPE (symbol) = type;
+  SYMBOL_DOMAIN (symbol) = VAR_DOMAIN;
+  SYMBOL_ACLASS_INDEX (symbol) = LOC_TYPEDEF;
+
+  return symbol;
+}
+
+/* Initialize the primitive type symbols of language LD.
+   The primitive type vector must have already been initialized.  */
+
+static void
+language_init_primitive_type_symbols (struct language_arch_info *lai,
+				      const struct language_defn *la,
+				      struct gdbarch *gdbarch)
+{
+  int n;
+  struct compunit_symtab *cust;
+  struct symtab *symtab;
+  struct block *static_block, *global_block;
 
-  for (p = ld->arch_info[la->la_language].primitive_type_vector;
-       (*p) != NULL;
-       p++)
+  gdb_assert (lai->primitive_type_vector != NULL);
+
+  for (n = 0; lai->primitive_type_vector[n] != NULL; ++n)
+    continue;
+
+  lai->primitive_type_symbols
+    = GDBARCH_OBSTACK_CALLOC (gdbarch, n + 1, struct symbol *);
+
+  for (n = 0; lai->primitive_type_vector[n] != NULL; ++n)
     {
-      if (strcmp (TYPE_NAME (*p), name) == 0)
-	return (*p);
+      lai->primitive_type_symbols[n]
+	= language_alloc_type_symbol (la->la_language,
+				      lai->primitive_type_vector[n]);
     }
-  return (NULL);
+
+  /* Note: The result of symbol lookup is normally a symbol *and* the block
+     it was found in (returned in global block_found).  Builtin types don't
+     live in blocks.  We *could* give them one, but there is no current need
+     so to keep things simple symbol lookup is extended to allow for
+     BLOCK_FOUND to be NULL.  */
+}
+
+/* See language.h.  */
+
+struct symbol *
+language_lookup_primitive_type_as_symbol (const struct language_defn *la,
+					  struct gdbarch *gdbarch,
+					  const char *name)
+{
+  struct language_gdbarch *ld = gdbarch_data (gdbarch,
+					      language_gdbarch_data);
+  struct language_arch_info *lai = &ld->arch_info[la->la_language];
+  struct type **typep;
+
+  typep = language_lookup_primitive_type_1 (lai, name);
+  if (typep == NULL)
+    return NULL;
+
+  /* The set of symbols is lazily initialized.  */
+  if (lai->primitive_type_symbols == NULL)
+    language_init_primitive_type_symbols (lai, la, gdbarch);
+
+  return lai->primitive_type_symbols[typep - lai->primitive_type_vector];
 }
 
 /* Initialize the language routines.  */
diff --git a/gdb/language.h b/gdb/language.h
index 73619ca..b6b4ebd 100644
--- a/gdb/language.h
+++ b/gdb/language.h
@@ -110,6 +110,11 @@ struct language_arch_info
      expressions, regardless of whether the program being debugged
      actually defines such a type.  */
   struct type **primitive_type_vector;
+
+  /* Symbol wrappers around primitive_type_vector, so that the symbol lookup
+     machinery can return them.  */
+  struct symbol **primitive_type_symbols;
+
   /* Type of elements of strings.  */
   struct type *string_char_type;
 
@@ -261,7 +266,8 @@ struct language_defn
        the part of symbol lookup where C looks up static and global
        variables.  */
 
-    struct symbol *(*la_lookup_symbol_nonlocal) (const char *,
+    struct symbol *(*la_lookup_symbol_nonlocal) (const struct language_defn *,
+						 const char *,
 						 const struct block *,
 						 const domain_enum);
 
@@ -404,9 +410,20 @@ struct type *language_bool_type (const struct language_defn *l,
 struct type *language_string_char_type (const struct language_defn *l,
 					struct gdbarch *gdbarch);
 
-struct type *language_lookup_primitive_type_by_name (const struct language_defn *l,
-						     struct gdbarch *gdbarch,
-						     const char *name);
+/* Look up type NAME in language L, and return its definition for architecture
+   GDBARCH.  Returns NULL if not found.  */
+
+struct type *language_lookup_primitive_type (const struct language_defn *l,
+					     struct gdbarch *gdbarch,
+					     const char *name);
+
+/* Wrapper around language_lookup_primitive_type to return the
+   corresponding symbol.  */
+
+struct symbol *
+  language_lookup_primitive_type_as_symbol (const struct language_defn *l,
+					    struct gdbarch *gdbarch,
+					    const char *name);
 
 
 /* These macros define the behaviour of the expression 
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 82384ca..d581764 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -2011,7 +2011,8 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 
       for (i = 0; VEC_iterate (symbolp, ls->labels.label_symbols, i, sym); ++i)
 	{
-	  struct program_space *pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+	  struct program_space *pspace
+	    = SYMTAB_PSPACE (symbol_symtab (sym));
 
 	  if (symbol_to_sal (&sal, state->funfirstline, sym)
 	      && maybe_add_address (state->addr_set, pspace, sal.pc))
@@ -2038,7 +2039,7 @@ convert_linespec_to_sals (struct linespec_state *state, linespec_p ls)
 
 	  for (i = 0; VEC_iterate (symbolp, ls->function_symbols, i, sym); ++i)
 	    {
-	      pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+	      pspace = SYMTAB_PSPACE (symbol_symtab (sym));
 	      set_current_program_space (pspace);
 	      if (symbol_to_sal (&sal, state->funfirstline, sym)
 		  && maybe_add_address (state->addr_set, pspace, sal.pc))
@@ -2776,8 +2777,8 @@ compare_symbols (const void *a, const void *b)
   struct symbol * const *sb = b;
   uintptr_t uia, uib;
 
-  uia = (uintptr_t) SYMTAB_PSPACE (SYMBOL_SYMTAB (*sa));
-  uib = (uintptr_t) SYMTAB_PSPACE (SYMBOL_SYMTAB (*sb));
+  uia = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (*sa));
+  uib = (uintptr_t) SYMTAB_PSPACE (symbol_symtab (*sb));
 
   if (uia < uib)
     return -1;
@@ -2921,8 +2922,8 @@ find_method (struct linespec_state *self, VEC (symtab_ptr) *file_symtabs,
 
       /* Program spaces that are executing startup should have
 	 been filtered out earlier.  */
-      gdb_assert (!SYMTAB_PSPACE (SYMBOL_SYMTAB (sym))->executing_startup);
-      pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+      pspace = SYMTAB_PSPACE (symbol_symtab (sym));
+      gdb_assert (!pspace->executing_startup);
       set_current_program_space (pspace);
       t = check_typedef (SYMBOL_TYPE (sym));
       find_methods (t, method_name, &result_names, &superclass_vec);
@@ -2931,7 +2932,8 @@ find_method (struct linespec_state *self, VEC (symtab_ptr) *file_symtabs,
 	 sure not to miss the last batch.  */
       if (ix == VEC_length (symbolp, sym_classes) - 1
 	  || (pspace
-	      != SYMTAB_PSPACE (SYMBOL_SYMTAB (VEC_index (symbolp, sym_classes,
+	      != SYMTAB_PSPACE (symbol_symtab (VEC_index (symbolp,
+							  sym_classes,
 							  ix + 1)))))
 	{
 	  /* If we did not find a direct implementation anywhere in
@@ -3247,7 +3249,7 @@ find_label_symbols (struct linespec_state *self,
       for (ix = 0;
 	   VEC_iterate (symbolp, function_symbols, ix, fn_sym); ++ix)
 	{
-	  set_current_program_space (SYMTAB_PSPACE (SYMBOL_SYMTAB (fn_sym)));
+	  set_current_program_space (SYMTAB_PSPACE (symbol_symtab (fn_sym)));
 	  block = SYMBOL_BLOCK_VALUE (fn_sym);
 	  sym = lookup_symbol (name, block, LABEL_DOMAIN, 0);
 
@@ -3654,10 +3656,10 @@ symbol_to_sal (struct symtab_and_line *result,
       if (SYMBOL_CLASS (sym) == LOC_LABEL && SYMBOL_VALUE_ADDRESS (sym) != 0)
 	{
 	  init_sal (result);
-	  result->symtab = SYMBOL_SYMTAB (sym);
+	  result->symtab = symbol_symtab (sym);
 	  result->line = SYMBOL_LINE (sym);
 	  result->pc = SYMBOL_VALUE_ADDRESS (sym);
-	  result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+	  result->pspace = SYMTAB_PSPACE (result->symtab);
 	  result->explicit_pc = 1;
 	  return 1;
 	}
@@ -3669,9 +3671,9 @@ symbol_to_sal (struct symtab_and_line *result,
 	{
 	  /* We know its line number.  */
 	  init_sal (result);
-	  result->symtab = SYMBOL_SYMTAB (sym);
+	  result->symtab = symbol_symtab (sym);
 	  result->line = SYMBOL_LINE (sym);
-	  result->pspace = SYMTAB_PSPACE (SYMBOL_SYMTAB (sym));
+	  result->pspace = SYMTAB_PSPACE (result->symtab);
 	  return 1;
 	}
     }
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index bcbd9b0..ed5d1d1 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -4596,7 +4596,7 @@ mylookup_symbol (char *name, const struct block *block,
 static void
 add_symbol (struct symbol *s, struct symtab *symtab, struct block *b)
 {
-  SYMBOL_SYMTAB (s) = symtab;
+  symbol_set_symtab (s, symtab);
   dict_add_symbol (BLOCK_DICT (b), s);
 }
 
diff --git a/gdb/p-exp.y b/gdb/p-exp.y
index 1c966cc..f44ef20 100644
--- a/gdb/p-exp.y
+++ b/gdb/p-exp.y
@@ -1709,9 +1709,12 @@ yylex (void)
 	  free (uptokstart);
 	  return TYPENAME;
         }
+
+    /* TODO(dje): Can this lookup of primitive types be deleted now?
+       Ref: PR 17684.  */
     yylval.tsym.type
-      = language_lookup_primitive_type_by_name (parse_language (pstate),
-						parse_gdbarch (pstate), tmp);
+      = language_lookup_primitive_type (parse_language (pstate),
+					parse_gdbarch (pstate), tmp);
     if (yylval.tsym.type != NULL)
       {
 	free (uptokstart);
diff --git a/gdb/parse.c b/gdb/parse.c
index d161776..877b082 100644
--- a/gdb/parse.c
+++ b/gdb/parse.c
@@ -1810,7 +1810,7 @@ operator_check_standard (struct expression *exp, int pos,
 
 	/* Check objfile where the variable itself is placed.
 	   SYMBOL_OBJ_SECTION (symbol) may be NULL.  */
-	if ((*objfile_func) (SYMBOL_OBJFILE (symbol), data))
+	if ((*objfile_func) (symbol_objfile (symbol), data))
 	  return 1;
 
 	/* Check objfile where is placed the code touching the variable.  */
diff --git a/gdb/printcmd.c b/gdb/printcmd.c
index d13b610..d6f5ae4 100644
--- a/gdb/printcmd.c
+++ b/gdb/printcmd.c
@@ -1251,8 +1251,11 @@ address_info (char *exp, int from_tty)
 			   current_language->la_language, DMGL_ANSI);
   printf_filtered ("\" is ");
   val = SYMBOL_VALUE (sym);
-  section = SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym);
-  gdbarch = get_objfile_arch (SYMBOL_OBJFILE (sym));
+  if (SYMBOL_IS_ARCH_OWNED (sym))
+    section = NULL;
+  else
+    section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
+  gdbarch = symbol_arch (sym);
 
   if (SYMBOL_COMPUTED_OPS (sym) != NULL)
     {
diff --git a/gdb/python/py-frame.c b/gdb/python/py-frame.c
index 62176df..d78d807 100644
--- a/gdb/python/py-frame.c
+++ b/gdb/python/py-frame.c
@@ -300,10 +300,8 @@ frapy_block (PyObject *self, PyObject *args)
 
   if (block)
     {
-      struct symtab *symt;
-
-      symt = SYMBOL_SYMTAB (BLOCK_FUNCTION (fn_block));
-      return block_to_block_object (block, SYMTAB_OBJFILE (symt));
+      return block_to_block_object
+	(block, symbol_objfile (BLOCK_FUNCTION (fn_block)));
     }
 
   Py_RETURN_NONE;
diff --git a/gdb/python/py-symbol.c b/gdb/python/py-symbol.c
index caf0a74..25bf0dd 100644
--- a/gdb/python/py-symbol.c
+++ b/gdb/python/py-symbol.c
@@ -87,7 +87,10 @@ sympy_get_symtab (PyObject *self, void *closure)
 
   SYMPY_REQUIRE_VALID (self, symbol);
 
-  return symtab_to_symtab_object (SYMBOL_SYMTAB (symbol));
+  if (SYMBOL_IS_ARCH_OWNED (symbol))
+    Py_RETURN_NONE;
+
+  return symtab_to_symtab_object (symbol_symtab (symbol));
 }
 
 static PyObject *
@@ -290,15 +293,15 @@ set_symbol (symbol_object *obj, struct symbol *symbol)
 {
   obj->symbol = symbol;
   obj->prev = NULL;
-  if (SYMBOL_SYMTAB (symbol))
+  if (!SYMBOL_IS_ARCH_OWNED (symbol)
+      && symbol_symtab (symbol) != NULL)
     {
-      obj->next = objfile_data (SYMBOL_OBJFILE (symbol),
-				sympy_objfile_data_key);
+      struct objfile *objfile = symbol_objfile (symbol);
 
+      obj->next = objfile_data (objfile, sympy_objfile_data_key);
       if (obj->next)
 	obj->next->prev = obj;
-      set_objfile_data (SYMBOL_OBJFILE (symbol),
-			sympy_objfile_data_key, obj);
+      set_objfile_data (objfile, sympy_objfile_data_key, obj);
     }
   else
     obj->next = NULL;
@@ -334,9 +337,11 @@ sympy_dealloc (PyObject *obj)
 
   if (sym_obj->prev)
     sym_obj->prev->next = sym_obj->next;
-  else if (sym_obj->symbol && SYMBOL_SYMTAB (sym_obj->symbol))
+  else if (sym_obj->symbol
+	   && !SYMBOL_IS_ARCH_OWNED (sym_obj->symbol)
+	   && symbol_symtab (sym_obj->symbol) != NULL)
     {
-      set_objfile_data (SYMBOL_OBJFILE (sym_obj->symbol),
+      set_objfile_data (symbol_objfile (sym_obj->symbol),
 			sympy_objfile_data_key, sym_obj->next);
     }
   if (sym_obj->next)
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 65d28e3..6b53555 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -556,7 +556,7 @@ btrace_call_history_src_line (struct ui_out *uiout,
     return;
 
   ui_out_field_string (uiout, "file",
-		       symtab_to_filename_for_display (sym->symtab));
+		       symtab_to_filename_for_display (symbol_symtab (sym)));
 
   begin = bfun->lbegin;
   end = bfun->lend;
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 5e0cc7a..54bb9e8 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -466,8 +466,12 @@ print_symbol (void *args)
   struct symbol *symbol = ((struct print_symbol_args *) args)->symbol;
   int depth = ((struct print_symbol_args *) args)->depth;
   struct ui_file *outfile = ((struct print_symbol_args *) args)->outfile;
-  struct obj_section *section = SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (symbol),
-						    symbol);
+  struct obj_section *section;
+
+  if (SYMBOL_IS_ARCH_OWNED (symbol))
+    section = NULL;
+  else
+    section = SYMBOL_OBJ_SECTION (symbol_objfile (symbol), symbol);
 
   print_spaces (depth, outfile);
   if (SYMBOL_DOMAIN (symbol) == LABEL_DOMAIN)
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 311ecbc..d470f7a 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -1153,12 +1153,15 @@ fixup_symbol_section (struct symbol *sym, struct objfile *objfile)
   if (!sym)
     return NULL;
 
+  if (SYMBOL_IS_ARCH_OWNED (sym))
+    return sym;
+
   /* We either have an OBJFILE, or we can get at it from the sym's
      symtab.  Anything else is a bug.  */
-  gdb_assert (objfile || SYMBOL_SYMTAB (sym));
+  gdb_assert (objfile || symbol_symtab (sym));
 
   if (objfile == NULL)
-    objfile = SYMBOL_OBJFILE (sym);
+    objfile = symbol_objfile (sym);
 
   if (SYMBOL_OBJ_SECTION (objfile, sym))
     return sym;
@@ -1393,6 +1396,13 @@ lookup_symbol_aux (const char *name, const struct block *block,
   struct symbol *sym;
   const struct language_defn *langdef;
 
+  /* Initialize block_found so that the language la_lookup_symbol_nonlocal
+     routines don't have to set it (to NULL) if a primitive type is found.
+     We do this early so that block_found is also NULL if no symbol is
+     found (though this is not part of the API, and callers cannot assume
+     this).  */
+  block_found = NULL;
+
   /* Make sure we do something sensible with is_a_field_of_this, since
      the callers that set this parameter to some non-null value will
      certainly use it later.  If we don't set it, the contents of
@@ -1443,7 +1453,7 @@ lookup_symbol_aux (const char *name, const struct block *block,
   /* Now do whatever is appropriate for LANGUAGE to look
      up static and global variables.  */
 
-  sym = langdef->la_lookup_symbol_nonlocal (name, block, domain);
+  sym = langdef->la_lookup_symbol_nonlocal (langdef, name, block, domain);
   if (sym != NULL)
     return sym;
 
@@ -1692,7 +1702,8 @@ lookup_symbol_via_quick_fns (struct objfile *objfile, int block_index,
 /* See symtab.h.  */
 
 struct symbol *
-basic_lookup_symbol_nonlocal (const char *name,
+basic_lookup_symbol_nonlocal (const struct language_defn *langdef,
+			      const char *name,
 			      const struct block *block,
 			      const domain_enum domain)
 {
@@ -1734,6 +1745,25 @@ basic_lookup_symbol_nonlocal (const char *name,
   if (sym != NULL)
     return sym;
 
+  /* If we didn't find a definition for a builtin type in the static block,
+     search for it now.  This is actually the right thing to do and can be
+     a massive performance win.  E.g., when debugging a program with lots of
+     shared libraries we could search all of them only to find out the
+     builtin type isn't defined in any of them.  This is common for types
+     like "void".  */
+  if (domain == VAR_DOMAIN)
+    {
+      struct gdbarch *gdbarch;
+
+      if (block == NULL)
+	gdbarch = target_gdbarch ();
+      else
+	gdbarch = block_gdbarch (block);
+      sym = language_lookup_primitive_type_as_symbol (langdef, gdbarch, name);
+      if (sym != NULL)
+	return sym;
+    }
+
   return lookup_global_symbol (name, block, domain);
 }
 
@@ -2701,10 +2731,11 @@ struct symtab_and_line
 find_function_start_sal (struct symbol *sym, int funfirstline)
 {
   struct symtab_and_line sal;
+  struct obj_section *section;
 
   fixup_symbol_section (sym, NULL);
-  sal = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)),
-			   SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym), 0);
+  section = SYMBOL_OBJ_SECTION (symbol_objfile (sym), sym);
+  sal = find_pc_sect_line (BLOCK_START (SYMBOL_BLOCK_VALUE (sym)), section, 0);
 
   /* We always should have a line for the function start address.
      If we don't, something is odd.  Create a plain SAL refering
@@ -2715,7 +2746,7 @@ find_function_start_sal (struct symbol *sym, int funfirstline)
       init_sal (&sal);
       sal.pspace = current_program_space;
       sal.pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
-      sal.section = SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym);
+      sal.section = section;
     }
 
   if (funfirstline)
@@ -2795,10 +2826,10 @@ skip_prologue_sal (struct symtab_and_line *sal)
     {
       fixup_symbol_section (sym, NULL);
 
+      objfile = symbol_objfile (sym);
       pc = BLOCK_START (SYMBOL_BLOCK_VALUE (sym));
-      section = SYMBOL_OBJ_SECTION (SYMBOL_OBJFILE (sym), sym);
+      section = SYMBOL_OBJ_SECTION (objfile, sym);
       name = SYMBOL_LINKAGE_NAME (sym);
-      objfile = SYMBOL_OBJFILE (sym);
     }
   else
     {
@@ -2830,7 +2861,8 @@ skip_prologue_sal (struct symtab_and_line *sal)
   /* Be conservative - allow direct PC (without skipping prologue) only if we
      have proven the CU (Compilation Unit) supports it.  sal->SYMTAB does not
      have to be set by the caller so we use SYM instead.  */
-  if (sym && COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (SYMBOL_SYMTAB (sym))))
+  if (sym
+      && COMPUNIT_LOCATIONS_VALID (SYMTAB_COMPUNIT (symbol_symtab (sym))))
     force_skip = 0;
 
   saved_pc = pc;
@@ -2895,7 +2927,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
      is aligned.  */
   if (!force_skip && sym && start_sal.symtab == NULL)
     {
-      pc = skip_prologue_using_lineinfo (pc, SYMBOL_SYMTAB (sym));
+      pc = skip_prologue_using_lineinfo (pc, symbol_symtab (sym));
       /* Recalculate the line number.  */
       start_sal = find_pc_sect_line (pc, section, 0);
     }
@@ -2935,7 +2967,7 @@ skip_prologue_sal (struct symtab_and_line *sal)
       && SYMBOL_LINE (BLOCK_FUNCTION (function_block)) != 0)
     {
       sal->line = SYMBOL_LINE (BLOCK_FUNCTION (function_block));
-      sal->symtab = SYMBOL_SYMTAB (BLOCK_FUNCTION (function_block));
+      sal->symtab = symbol_symtab (BLOCK_FUNCTION (function_block));
     }
 }
 
@@ -3417,8 +3449,8 @@ compare_search_syms (const void *sa, const void *sb)
   struct symbol_search *sym_b = *(struct symbol_search **) sb;
   int c;
 
-  c = FILENAME_CMP (SYMBOL_SYMTAB (sym_a->symbol)->filename,
-		    SYMBOL_SYMTAB (sym_b->symbol)->filename);
+  c = FILENAME_CMP (symbol_symtab (sym_a->symbol)->filename,
+		    symbol_symtab (sym_b->symbol)->filename);
   if (c != 0)
     return c;
 
@@ -3700,7 +3732,7 @@ search_symbols (const char *regexp, enum search_domain kind,
 	b = BLOCKVECTOR_BLOCK (bv, i);
 	ALL_BLOCK_SYMBOLS (b, iter, sym)
 	  {
-	    struct symtab *real_symtab = SYMBOL_SYMTAB (sym);
+	    struct symtab *real_symtab = symbol_symtab (sym);
 
 	    QUIT;
 
@@ -3819,7 +3851,7 @@ print_symbol_info (enum search_domain kind,
 		   struct symbol *sym,
 		   int block, const char *last)
 {
-  struct symtab *s = SYMBOL_SYMTAB (sym);
+  struct symtab *s = symbol_symtab (sym);
   const char *s_filename = symtab_to_filename_for_display (s);
 
   if (last == NULL || filename_cmp (last, s_filename) != 0)
@@ -3918,7 +3950,7 @@ symtab_symbol_info (char *regexp, enum search_domain kind, int from_tty)
 			     p->block,
 			     last_filename);
 	  last_filename
-	    = symtab_to_filename_for_display (SYMBOL_SYMTAB (p->symbol));
+	    = symtab_to_filename_for_display (symbol_symtab (p->symbol));
 	}
     }
 
@@ -4004,7 +4036,7 @@ rbreak_command (char *regexp, int from_tty)
     {
       if (p->msymbol.minsym == NULL)
 	{
-	  struct symtab *symtab = SYMBOL_SYMTAB (p->symbol);
+	  struct symtab *symtab = symbol_symtab (p->symbol);
 	  const char *fullname = symtab_to_fullname (symtab);
 
 	  int newlen = (strlen (fullname)
@@ -5186,6 +5218,43 @@ allocate_template_symbol (struct objfile *objfile)
   return result;
 }
 
+/* See symtab.h.  */
+
+struct objfile *
+symbol_objfile (const struct symbol *symbol)
+{
+  gdb_assert (!SYMBOL_IS_ARCH_OWNED (symbol));
+  return SYMTAB_OBJFILE (symbol->owner.symtab);
+}
+
+/* See symtab.h.  */
+
+struct gdbarch *
+symbol_arch (const struct symbol *symbol)
+{
+  if (SYMBOL_IS_ARCH_OWNED (symbol))
+    return symbol->owner.arch;
+  return get_objfile_arch (SYMTAB_OBJFILE (symbol->owner.symtab));
+}
+
+/* See symtab.h.  */
+
+struct symtab *
+symbol_symtab (const struct symbol *symbol)
+{
+  gdb_assert (!SYMBOL_IS_ARCH_OWNED (symbol));
+  return symbol->owner.symtab;
+}
+
+/* See symtab.h.  */
+
+void
+symbol_set_symtab (struct symbol *symbol, struct symtab *symtab)
+{
+  gdb_assert (!SYMBOL_IS_ARCH_OWNED (symbol));
+  symbol->owner.symtab = symtab;
+}
+
 
 
 void
diff --git a/gdb/symtab.h b/gdb/symtab.h
index dc4c055..6ca8afd 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -696,10 +696,19 @@ struct symbol
 
   struct type *type;
 
-  /* The symbol table containing this symbol.  This is the file
-     associated with LINE.  It can be NULL during symbols read-in but it is
-     never NULL during normal operation.  */
-  struct symtab *symtab;
+  /* The owner of this symbol.
+     Which one to use is defined by symbol.is_arch_owned.  */
+
+  union
+  {
+    /* The symbol table containing this symbol.  This is the file associated
+       with LINE.  It can be NULL during symbols read-in but it is never NULL
+       during normal operation.  */
+    struct symtab *symtab;
+
+    /* For types defined by the architecture.  */
+    struct gdbarch *arch;
+  } owner;
 
   /* Domain code.  */
 
@@ -711,6 +720,11 @@ struct symbol
 
   unsigned int aclass_index : SYMBOL_ACLASS_BITS;
 
+  /* If non-zero then symbol is arch-owned, use owner.arch.
+     Otherwise symbol is objfile-owned, use owner.symtab.  */
+
+  unsigned int is_arch_owned : 1;
+
   /* Whether this is an argument.  */
 
   unsigned is_argument : 1;
@@ -727,6 +741,7 @@ struct symbol
      SYMBOL_INLINED set) this is the line number of the function's call
      site.  Inlined function symbols are not definitions, and they are
      never found by symbol table lookup.
+     If this symbol is arch-owned, LINE shall be zero.
 
      FIXME: Should we really make the assumption that nobody will try
      to debug files longer than 64K lines?  What about machine
@@ -754,22 +769,24 @@ struct symbol
 
 extern const struct symbol_impl *symbol_impls;
 
+/* Note: There is no accessor macro for symbol.owner because it is
+   "private".  */
+
 #define SYMBOL_DOMAIN(symbol)	(symbol)->domain
 #define SYMBOL_IMPL(symbol)		(symbol_impls[(symbol)->aclass_index])
 #define SYMBOL_ACLASS_INDEX(symbol)	(symbol)->aclass_index
 #define SYMBOL_CLASS(symbol)		(SYMBOL_IMPL (symbol).aclass)
+#define SYMBOL_IS_ARCH_OWNED(symbol)	((symbol)->is_arch_owned)
 #define SYMBOL_IS_ARGUMENT(symbol)	(symbol)->is_argument
 #define SYMBOL_INLINED(symbol)		(symbol)->is_inlined
 #define SYMBOL_IS_CPLUS_TEMPLATE_FUNCTION(symbol) \
   (symbol)->is_cplus_template_function
 #define SYMBOL_TYPE(symbol)		(symbol)->type
 #define SYMBOL_LINE(symbol)		(symbol)->line
-#define SYMBOL_SYMTAB(symbol)		(symbol)->symtab
 #define SYMBOL_COMPUTED_OPS(symbol)	(SYMBOL_IMPL (symbol).ops_computed)
 #define SYMBOL_BLOCK_OPS(symbol)	(SYMBOL_IMPL (symbol).ops_block)
 #define SYMBOL_REGISTER_OPS(symbol)	(SYMBOL_IMPL (symbol).ops_register)
 #define SYMBOL_LOCATION_BATON(symbol)   (symbol)->aux_value
-#define SYMBOL_OBJFILE(symbol)		SYMTAB_OBJFILE (SYMBOL_SYMTAB (symbol))
 
 extern int register_symbol_computed_impl (enum address_class,
 					  const struct symbol_computed_ops *);
@@ -780,6 +797,28 @@ extern int register_symbol_block_impl (enum address_class aclass,
 extern int register_symbol_register_impl (enum address_class,
 					  const struct symbol_register_ops *);
 
+/* Return the OBJFILE of SYMBOL.
+   It is an error to call this if symbol.is_arch_owned is true, which
+   only happens for architecture-provided types.  */
+
+extern struct objfile *symbol_objfile (const struct symbol *symbol);
+
+/* Return the ARCH of SYMBOL.  */
+
+extern struct gdbarch *symbol_arch (const struct symbol *symbol);
+
+/* Return the SYMTAB of SYMBOL.
+   It is an error to call this if symbol.is_arch_owned is true, which
+   only happens for architecture-provided types.  */
+
+extern struct symtab *symbol_symtab (const struct symbol *symbol);
+
+/* Set the symtab of SYMBOL to SYMTAB.
+   It is an error to call this if symbol.is_arch_owned is true, which
+   only happens for architecture-provided types.  */
+
+extern void symbol_set_symtab (struct symbol *symbol, struct symtab *symtab);
+
 /* An instance of this type is used to represent a C++ template
    function.  It includes a "struct symbol" as a kind of base class;
    users downcast to "struct template_symbol *" when needed.  A symbol
@@ -1155,9 +1194,11 @@ extern struct symbol *lookup_symbol (const char *, const struct block *,
    that can't think of anything better to do.
    This implements the C lookup rules.  */
 
-extern struct symbol *basic_lookup_symbol_nonlocal (const char *,
-						    const struct block *,
-						    const domain_enum);
+extern struct symbol *
+  basic_lookup_symbol_nonlocal (const struct language_defn *langdef,
+				const char *,
+				const struct block *,
+				const domain_enum);
 
 /* Some helper functions for languages that need to write their own
    lookup_symbol_nonlocal functions.  */
diff --git a/gdb/tracepoint.c b/gdb/tracepoint.c
index b8ef2e1..38a3491 100644
--- a/gdb/tracepoint.c
+++ b/gdb/tracepoint.c
@@ -2739,7 +2739,7 @@ scope_info (char *args, int from_tty)
 	  if (symname == NULL || *symname == '\0')
 	    continue;		/* Probably botched, certainly useless.  */
 
-	  gdbarch = get_objfile_arch (SYMBOL_OBJFILE (sym));
+	  gdbarch = symbol_arch (sym);
 
 	  printf_filtered ("Symbol %s is ", symname);
 
diff --git a/gdb/valops.c b/gdb/valops.c
index 4d3059e..841785c 100644
--- a/gdb/valops.c
+++ b/gdb/valops.c
@@ -139,7 +139,7 @@ find_function_in_inferior (const char *name, struct objfile **objf_p)
 	}
 
       if (objf_p)
-	*objf_p = SYMBOL_OBJFILE (sym);
+	*objf_p = symbol_objfile (sym);
 
       return value_of_variable (sym, NULL);
     }
