mirror of
				https://gitlab.com/freepascal.org/fpc/source.git
				synced 2025-11-04 06:39:25 +01:00 
			
		
		
		
	* fixed several omissions that could cause the dynamic linker not to
register required classes:
    + add lazy references to classes referred to in the current unit
    + define reference symbols for classes defined in the current unit
    + add lazy references to parent classes of classes defined in the current
      unit
git-svn-id: branches/objc@13679 -
			
			
This commit is contained in:
		
							parent
							
								
									cd24bb4df6
								
							
						
					
					
						commit
						e393446769
					
				@ -254,7 +254,7 @@ interface
 | 
				
			|||||||
      TAsmDirective=(
 | 
					      TAsmDirective=(
 | 
				
			||||||
        asd_non_lazy_symbol_pointer,asd_indirect_symbol,asd_lazy_symbol_pointer,
 | 
					        asd_non_lazy_symbol_pointer,asd_indirect_symbol,asd_lazy_symbol_pointer,
 | 
				
			||||||
        asd_extern,asd_nasm_import, asd_toc_entry, asd_mod_init_func, asd_mod_term_func,
 | 
					        asd_extern,asd_nasm_import, asd_toc_entry, asd_mod_init_func, asd_mod_term_func,
 | 
				
			||||||
        asd_reference,asd_no_dead_strip,asd_weak_reference
 | 
					        asd_reference,asd_no_dead_strip,asd_weak_reference,asd_lazy_reference
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const
 | 
					    const
 | 
				
			||||||
@ -264,7 +264,7 @@ interface
 | 
				
			|||||||
      directivestr : array[TAsmDirective] of string[23]=(
 | 
					      directivestr : array[TAsmDirective] of string[23]=(
 | 
				
			||||||
        'non_lazy_symbol_pointer','indirect_symbol','lazy_symbol_pointer',
 | 
					        'non_lazy_symbol_pointer','indirect_symbol','lazy_symbol_pointer',
 | 
				
			||||||
        'extern','nasm_import', 'tc', 'mod_init_func', 'mod_term_func', 'reference',
 | 
					        'extern','nasm_import', 'tc', 'mod_init_func', 'mod_term_func', 'reference',
 | 
				
			||||||
        'no_dead_strip','weak_reference'
 | 
					        'no_dead_strip','weak_reference','lazy_reference'
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    type
 | 
					    type
 | 
				
			||||||
@ -313,13 +313,16 @@ interface
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
       { Generates a common label }
 | 
					       { Generates a common label }
 | 
				
			||||||
       tai_symbol = class(tai)
 | 
					       tai_symbol = class(tai)
 | 
				
			||||||
          is_global : boolean;
 | 
					 | 
				
			||||||
          sym       : tasmsymbol;
 | 
					          sym       : tasmsymbol;
 | 
				
			||||||
 | 
					          value     : puint;
 | 
				
			||||||
          size      : longint;
 | 
					          size      : longint;
 | 
				
			||||||
 | 
					          is_global,
 | 
				
			||||||
 | 
					          has_value : boolean;
 | 
				
			||||||
          constructor Create(_sym:tasmsymbol;siz:longint);
 | 
					          constructor Create(_sym:tasmsymbol;siz:longint);
 | 
				
			||||||
          constructor Create_Global(_sym:tasmsymbol;siz:longint);
 | 
					          constructor Create_Global(_sym:tasmsymbol;siz:longint);
 | 
				
			||||||
          constructor Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint);
 | 
					          constructor Createname(const _name : string;_symtyp:Tasmsymtype;siz:longint);
 | 
				
			||||||
          constructor Createname_global(const _name : string;_symtyp:Tasmsymtype;siz:longint);
 | 
					          constructor Createname_global(const _name : string;_symtyp:Tasmsymtype;siz:longint);
 | 
				
			||||||
 | 
					          constructor Createname_global_value(const _name : string;_symtyp:Tasmsymtype;siz:longint;val:ptruint);
 | 
				
			||||||
          constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
 | 
					          constructor ppuload(t:taitype;ppufile:tcompilerppufile);override;
 | 
				
			||||||
          procedure ppuwrite(ppufile:tcompilerppufile);override;
 | 
					          procedure ppuwrite(ppufile:tcompilerppufile);override;
 | 
				
			||||||
          procedure derefimpl;override;
 | 
					          procedure derefimpl;override;
 | 
				
			||||||
@ -946,6 +949,14 @@ implementation
 | 
				
			|||||||
      end;
 | 
					      end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor tai_symbol.createname_global_value(const _name: string;_symtyp: tasmsymtype; siz: longint; val: ptruint);
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					        Createname_global(_name,_symtyp,siz);
 | 
				
			||||||
 | 
					        value:=val;
 | 
				
			||||||
 | 
					        has_value:=true;
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    constructor tai_symbol.ppuload(t:taitype;ppufile:tcompilerppufile);
 | 
					    constructor tai_symbol.ppuload(t:taitype;ppufile:tcompilerppufile);
 | 
				
			||||||
      begin
 | 
					      begin
 | 
				
			||||||
        inherited ppuload(t,ppufile);
 | 
					        inherited ppuload(t,ppufile);
 | 
				
			||||||
 | 
				
			|||||||
@ -1042,7 +1042,10 @@ implementation
 | 
				
			|||||||
                         AsmWriteLn(',' + sepChar + 'function');
 | 
					                         AsmWriteLn(',' + sepChar + 'function');
 | 
				
			||||||
                     end;
 | 
					                     end;
 | 
				
			||||||
                 end;
 | 
					                 end;
 | 
				
			||||||
               AsmWriteLn(tai_symbol(hp).sym.name + ':');
 | 
					               if not(tai_symbol(hp).has_value) then
 | 
				
			||||||
 | 
					                 AsmWriteLn(tai_symbol(hp).sym.name + ':')
 | 
				
			||||||
 | 
					               else
 | 
				
			||||||
 | 
					                 AsmWriteLn(tai_symbol(hp).sym.name + '=' + tostr(tai_symbol(hp).value));
 | 
				
			||||||
             end;
 | 
					             end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
           ait_symbol_end :
 | 
					           ait_symbol_end :
 | 
				
			||||||
 | 
				
			|||||||
@ -992,7 +992,12 @@ Implementation
 | 
				
			|||||||
                 Tai_section(hp).sec:=ObjData.CurrObjSec;
 | 
					                 Tai_section(hp).sec:=ObjData.CurrObjSec;
 | 
				
			||||||
               end;
 | 
					               end;
 | 
				
			||||||
             ait_symbol :
 | 
					             ait_symbol :
 | 
				
			||||||
               ObjData.SymbolDefine(Tai_symbol(hp).sym);
 | 
					               begin
 | 
				
			||||||
 | 
					                 { needs extra support in the internal assembler }
 | 
				
			||||||
 | 
					                 if tai_symbol(hp).has_value then
 | 
				
			||||||
 | 
					                   internalerror(2009090804);
 | 
				
			||||||
 | 
					                 ObjData.SymbolDefine(Tai_symbol(hp).sym);
 | 
				
			||||||
 | 
					               end;
 | 
				
			||||||
             ait_label :
 | 
					             ait_label :
 | 
				
			||||||
               ObjData.SymbolDefine(Tai_label(hp).labsym);
 | 
					               ObjData.SymbolDefine(Tai_label(hp).labsym);
 | 
				
			||||||
             ait_string :
 | 
					             ait_string :
 | 
				
			||||||
 | 
				
			|||||||
@ -895,6 +895,8 @@ interface
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
           ait_symbol :
 | 
					           ait_symbol :
 | 
				
			||||||
             begin
 | 
					             begin
 | 
				
			||||||
 | 
					               if tai_symbol(hp).has_value then
 | 
				
			||||||
 | 
					                 internalerror(2009090803);
 | 
				
			||||||
               if tai_symbol(hp).is_global then
 | 
					               if tai_symbol(hp).is_global then
 | 
				
			||||||
                begin
 | 
					                begin
 | 
				
			||||||
                  AsmWrite(#9'GLOBAL ');
 | 
					                  AsmWrite(#9'GLOBAL ');
 | 
				
			||||||
 | 
				
			|||||||
@ -89,6 +89,7 @@ procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpo
 | 
				
			|||||||
  var
 | 
					  var
 | 
				
			||||||
    reflab : tasmlabel;
 | 
					    reflab : tasmlabel;
 | 
				
			||||||
    strlab : tasmsymbol;
 | 
					    strlab : tasmsymbol;
 | 
				
			||||||
 | 
					    classname: string;
 | 
				
			||||||
  begin
 | 
					  begin
 | 
				
			||||||
    { have we already generated a reference for this string entry? }
 | 
					    { have we already generated a reference for this string entry? }
 | 
				
			||||||
    if not assigned(entry^.Data) then
 | 
					    if not assigned(entry^.Data) then
 | 
				
			||||||
@ -104,7 +105,16 @@ procedure objcfinishstringrefpoolentry(entry: phashsetitem; stringpool: tconstpo
 | 
				
			|||||||
        new_section(current_asmdata.asmlists[al_objc_pools],refsec,reflab.name,sizeof(pint));
 | 
					        new_section(current_asmdata.asmlists[al_objc_pools],refsec,reflab.name,sizeof(pint));
 | 
				
			||||||
        current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(reflab));
 | 
					        current_asmdata.asmlists[al_objc_pools].concat(Tai_label.Create(reflab));
 | 
				
			||||||
        current_asmdata.asmlists[al_objc_pools].concat(Tai_const.Create_sym(strlab));
 | 
					        current_asmdata.asmlists[al_objc_pools].concat(Tai_const.Create_sym(strlab));
 | 
				
			||||||
    end;
 | 
					
 | 
				
			||||||
 | 
					        { in case of a class reference, also add a lazy symbol reference for
 | 
				
			||||||
 | 
					          the class (the linker requires this). }
 | 
				
			||||||
 | 
					        if (refsec=sec_objc_cls_refs) then
 | 
				
			||||||
 | 
					          begin
 | 
				
			||||||
 | 
					            setlength(classname,entry^.keylength);
 | 
				
			||||||
 | 
					            move(entry^.key^,classname[1],entry^.keylength);
 | 
				
			||||||
 | 
					            current_asmdata.asmlists[al_objc_pools].concat(tai_directive.Create(asd_lazy_reference,'.objc_class_name_'+classname));
 | 
				
			||||||
 | 
					          end;
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -387,7 +397,7 @@ procedure gen_objc1_classes_sections(list:TAsmList; objclss: tobjectdef; out cla
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{ Generate the rtti sections for all obj-c classes defined in st, and return
 | 
					{ Generate the rtti sections for all obj-c classes defined in st, and return
 | 
				
			||||||
  these classes in the classes list. }
 | 
					  these classes in the classes list. }
 | 
				
			||||||
procedure gen_objc1_rtti_sections(list:TAsmList; st:TSymtable; var classes: tfpobjectlist);
 | 
					procedure gen_objc1_rtti_sections(list:TAsmList; st:TSymtable; var classsyms, classdefs: tfpobjectlist);
 | 
				
			||||||
  var
 | 
					  var
 | 
				
			||||||
    i: longint;
 | 
					    i: longint;
 | 
				
			||||||
    def: tdef;
 | 
					    def: tdef;
 | 
				
			||||||
@ -403,7 +413,8 @@ procedure gen_objc1_rtti_sections(list:TAsmList; st:TSymtable; var classes: tfpo
 | 
				
			|||||||
           not(oo_is_external in tobjectdef(def).objectoptions) then
 | 
					           not(oo_is_external in tobjectdef(def).objectoptions) then
 | 
				
			||||||
          begin
 | 
					          begin
 | 
				
			||||||
            gen_objc1_classes_sections(list,tobjectdef(def),sym);
 | 
					            gen_objc1_classes_sections(list,tobjectdef(def),sym);
 | 
				
			||||||
            classes.add(sym);
 | 
					            classsyms.add(sym);
 | 
				
			||||||
 | 
					            classdefs.add(def);
 | 
				
			||||||
          end;
 | 
					          end;
 | 
				
			||||||
      end;
 | 
					      end;
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
@ -411,12 +422,14 @@ procedure gen_objc1_rtti_sections(list:TAsmList; st:TSymtable; var classes: tfpo
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
{ Generate the global information sections (objc_symbols and objc_module_info)
 | 
					{ Generate the global information sections (objc_symbols and objc_module_info)
 | 
				
			||||||
  for this module. }
 | 
					  for this module. }
 | 
				
			||||||
procedure gen_objc1_info_sections(list: tasmlist; classes: tfpobjectlist);
 | 
					procedure gen_objc1_info_sections(list: tasmlist; classsyms,classdefs: tfpobjectlist);
 | 
				
			||||||
  var
 | 
					  var
 | 
				
			||||||
    i: longint;
 | 
					    i: longint;
 | 
				
			||||||
    sym : TAsmSymbol;
 | 
					    sym : TAsmSymbol;
 | 
				
			||||||
 | 
					    parent: tobjectdef;
 | 
				
			||||||
 | 
					    superclasses: tfpobjectlist;
 | 
				
			||||||
  begin
 | 
					  begin
 | 
				
			||||||
    if (classes.count<>0) then
 | 
					    if (classsyms.count<>0) then
 | 
				
			||||||
      begin
 | 
					      begin
 | 
				
			||||||
        new_section(list,sec_objc_symbols,'_OBJC_SYMBOLS',sizeof(pint));
 | 
					        new_section(list,sec_objc_symbols,'_OBJC_SYMBOLS',sizeof(pint));
 | 
				
			||||||
        sym := current_asmdata.RefAsmSymbol(target_asm.labelprefix+'_OBJC_SYMBOLS');
 | 
					        sym := current_asmdata.RefAsmSymbol(target_asm.labelprefix+'_OBJC_SYMBOLS');
 | 
				
			||||||
@ -428,12 +441,12 @@ procedure gen_objc1_info_sections(list: tasmlist; classes: tfpobjectlist);
 | 
				
			|||||||
        { ??? (From Clang: always 0, pointer to some selector) }
 | 
					        { ??? (From Clang: always 0, pointer to some selector) }
 | 
				
			||||||
        list.Concat(Tai_const.Create_pint(0));
 | 
					        list.Concat(Tai_const.Create_pint(0));
 | 
				
			||||||
        { From Clang: number of defined classes }
 | 
					        { From Clang: number of defined classes }
 | 
				
			||||||
        list.Concat(Tai_const.Create_16bit(classes.count));
 | 
					        list.Concat(Tai_const.Create_16bit(classsyms.count));
 | 
				
			||||||
        { From Clang: number of defined categories }
 | 
					        { From Clang: number of defined categories }
 | 
				
			||||||
        list.Concat(Tai_const.Create_16bit(0));
 | 
					        list.Concat(Tai_const.Create_16bit(0));
 | 
				
			||||||
        { first all classes }
 | 
					        { first all classes }
 | 
				
			||||||
        for i:=0 to classes.count-1 do
 | 
					        for i:=0 to classsyms.count-1 do
 | 
				
			||||||
          list.Concat(Tai_const.Create_sym(tasmsymbol(classes[i])));
 | 
					          list.Concat(Tai_const.Create_sym(tasmsymbol(classsyms[i])));
 | 
				
			||||||
        { then all categories }
 | 
					        { then all categories }
 | 
				
			||||||
     end
 | 
					     end
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
@ -451,12 +464,30 @@ procedure gen_objc1_info_sections(list: tasmlist; classes: tfpobjectlist);
 | 
				
			|||||||
      list.Concat(Tai_const.Create_sym(sym))
 | 
					      list.Concat(Tai_const.Create_sym(sym))
 | 
				
			||||||
    else
 | 
					    else
 | 
				
			||||||
      list.concat(tai_const.create_pint(0));
 | 
					      list.concat(tai_const.create_pint(0));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    { Add lazy references to parent classes of all classes defined in this unit }
 | 
				
			||||||
 | 
					    superclasses:=tfpobjectlist.create(false);
 | 
				
			||||||
 | 
					    for i:=0 to classdefs.count-1 do
 | 
				
			||||||
 | 
					      begin
 | 
				
			||||||
 | 
					        parent:=tobjectdef(classdefs[i]).childof;
 | 
				
			||||||
 | 
					        if assigned(parent) and
 | 
				
			||||||
 | 
					           (superclasses.indexof(parent)=-1) then
 | 
				
			||||||
 | 
					          begin
 | 
				
			||||||
 | 
					            list.concat(tai_directive.create(asd_lazy_reference,'.objc_class_name_'+parent.objextname^));
 | 
				
			||||||
 | 
					            superclasses.add(parent);
 | 
				
			||||||
 | 
					          end;
 | 
				
			||||||
 | 
					      end;
 | 
				
			||||||
 | 
					    superclasses.free;
 | 
				
			||||||
 | 
					    { reference symbols for all classes declaredin this unit }
 | 
				
			||||||
 | 
					    for i:=0 to classdefs.count-1 do
 | 
				
			||||||
 | 
					      list.concat(tai_symbol.Createname_global_value('.objc_class_name_'+tobjectdef(classdefs[i]).objextname^,AT_DATA,0,0));
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
 | 
					procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
 | 
				
			||||||
  var
 | 
					  var
 | 
				
			||||||
    classes: tfpobjectlist;
 | 
					    classsyms,
 | 
				
			||||||
 | 
					    classdefs: tfpobjectlist;
 | 
				
			||||||
  begin
 | 
					  begin
 | 
				
			||||||
    if (m_objectivec1 in current_settings.modeswitches) then
 | 
					    if (m_objectivec1 in current_settings.modeswitches) then
 | 
				
			||||||
      begin
 | 
					      begin
 | 
				
			||||||
@ -470,11 +501,13 @@ procedure MaybeGenerateObjectiveCImageInfo(globalst, localst: tsymtable);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        { generate rtti for all obj-c classes, protocols (todo) and categories (todo)
 | 
					        { generate rtti for all obj-c classes, protocols (todo) and categories (todo)
 | 
				
			||||||
          defined in this module. }
 | 
					          defined in this module. }
 | 
				
			||||||
        classes:=tfpobjectlist.create(false);
 | 
					        classsyms:=tfpobjectlist.create(false);
 | 
				
			||||||
        gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst,classes);
 | 
					        classdefs:=tfpobjectlist.create(false);
 | 
				
			||||||
        gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],localst,classes);
 | 
					        gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],globalst,classsyms,classdefs);
 | 
				
			||||||
        gen_objc1_info_sections(current_asmdata.asmlists[al_objc_data],classes);
 | 
					        gen_objc1_rtti_sections(current_asmdata.asmlists[al_objc_data],localst,classsyms,classdefs);
 | 
				
			||||||
        classes.free;
 | 
					        gen_objc1_info_sections(current_asmdata.asmlists[al_objc_data],classsyms,classdefs);
 | 
				
			||||||
 | 
					        classsyms.free;
 | 
				
			||||||
 | 
					        classdefs.free;
 | 
				
			||||||
      end;
 | 
					      end;
 | 
				
			||||||
  end;
 | 
					  end;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -705,6 +705,8 @@ implementation
 | 
				
			|||||||
             end;
 | 
					             end;
 | 
				
			||||||
           ait_symbol :
 | 
					           ait_symbol :
 | 
				
			||||||
             begin
 | 
					             begin
 | 
				
			||||||
 | 
					               if tai_symbol(hp).has_value then
 | 
				
			||||||
 | 
					                 internalerror(2009090802);
 | 
				
			||||||
               if tai_symbol(hp).is_global then
 | 
					               if tai_symbol(hp).is_global then
 | 
				
			||||||
                 AsmWriteLn(#9'PUBLIC'#9+tai_symbol(hp).sym.name);
 | 
					                 AsmWriteLn(#9'PUBLIC'#9+tai_symbol(hp).sym.name);
 | 
				
			||||||
               AsmWrite(tai_symbol(hp).sym.name);
 | 
					               AsmWrite(tai_symbol(hp).sym.name);
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user