[m-rev.] for review: fix bug #196: binary compatiblity checks in C grade don't work

Paul Bone paul at bone.id.au
Mon Jul 25 09:55:31 AEST 2016


On Sun, Jul 17, 2016 at 01:49:49PM +1000, Julien Fischer wrote:
> 
> Hi Zoltan,
> 
> On Thu, 14 Jul 2016, Zoltan Somogyi wrote:
> >On Fri, 15 Jul 2016 01:16:25 +1000 (AEST), Julien Fischer <jfischer at opturion.com> wrote:
> >>Is anyone intending to review this one?  In the absence of any comments
> >>I'll commit it later today.
> >
> >I thought I already reviewed the idea, and said that I would prefer
> >to fix the problem by exporting a function that refers to the value
> >of MR_GRADE_VAR. I think this would be more robust in the face
> >of compiler optimizations, though it does have the slight downside
> >of adding one symbol per module to the executable's symbol table.
> 
> The following diff implements the above.
> 
> Julien.
> 
> ---------------
> 
> Fix bug #196: binary compatibility checks in C grades do not work.
> 
> These have been broken since 2011 because GCC and clang (at least) began
> optimising away the MR_grade variable we emit at the end of each generated .c
> file.  The fix is to replace the MR_grade variable with an exported function
> that references MR_GRADE_VAR in each generated .c file.
> 
> compiler/llds_out_file.m:
> compiler/mlds_to_c.m:
> util/mkinit.c:
>      In each generated .c file, emit an exported function that references
>      MR_GRADE_VAR.

I just upgraded to ROTD 2016-07-18 and noticed this new warning, it wasn't
there before:

Mercury/asm_fast.gc.debug.stseg/x86_64-pc-linux-gnu/Mercury/cs/js_write_grammar_init.c:3380:13: warning: no previous prototype for ‘mercury_init_grade_check’ [-Wmissing-prototypes]

I'm using gcc 5.4.0 20160609 on x86_64.  The warning seems to be grade
independant.  It also benign, things otherwise work as expected.


-- 
Paul Bone


> 
> diff --git a/compiler/llds_out_file.m b/compiler/llds_out_file.m
> index f437ce4..e02410e 100644
> --- a/compiler/llds_out_file.m
> +++ b/compiler/llds_out_file.m
> @@ -482,6 +482,10 @@ output_c_module_init_list(Info, ModuleName, AnnotatedModules, RttiDatas,
>          io.write_string("required_final(void);\n", !IO)
>      ),
> 
> +    io.write_string("const char *", !IO),
> +    output_init_name(ModuleName, !IO),
> +    io.write_string("grade_check(void);\n", !IO),
> +
>      io.write_string("\n", !IO),
> 
>      io.write_string("void ", !IO),
> @@ -609,14 +613,19 @@ output_c_module_init_list(Info, ModuleName, AnnotatedModules, RttiDatas,
>          io.write_string("required_final(void)\n", !IO),
>          io.write_string("{\n", !IO),
>          output_required_init_or_final_calls(FinalPredNames, !IO),
> -        io.write_string("}\n", !IO)
> +        io.write_string("}\n", !IO),
> +        io.nl(!IO)
>      ),
> 
>      io.write_string(
> -        "/* ensure everything is compiled with the same grade */\n",
> +        "// Ensure everything is compiled with the same grade.\n",
>          !IO),
> -    io.write_string(
> -        "static const void *const MR_grade = &MR_GRADE_VAR;\n", !IO).
> +    io.write_string("const char *", !IO),
> +    output_init_name(ModuleName, !IO),
> +    io.write_string("grade_check(void)\n", !IO),
> +    io.write_string("{\n", !IO),
> +    io.write_string("    return &MR_GRADE_VAR;\n", !IO),
> +    io.write_string("}\n", !IO).
> 
>  :- pred module_defines_label_with_layout(llds_out_info::in,
>      annotated_c_module::in) is semidet.
> diff --git a/compiler/mlds_to_c.m b/compiler/mlds_to_c.m
> index eeb570c..9a9608d 100644
> --- a/compiler/mlds_to_c.m
> +++ b/compiler/mlds_to_c.m
> @@ -455,7 +455,7 @@ mlds_output_src_file(Opts, Indent, MLDS, !IO) :-
>      mlds_output_init_fn_defns(Opts, MLDS_ModuleName, FuncDefns,
>          TypeCtorInfoDefns, AllocSites, InitPreds, FinalPreds, !IO),
>      io.nl(!IO),
> -    mlds_output_grade_var(!IO),
> +    mlds_output_grade_check_fn_defn(MLDS_ModuleName, !IO),
>      io.nl(!IO),
>      mlds_output_src_end(Indent, ModuleName, !IO).
> 
> @@ -672,15 +672,16 @@ mlds_output_auto_gen_comment(Opts, ModuleName, !IO) :-
>      % file gets compiled with. This ensures that we don't try to link objects
>      % files compiled in different grades.
>      %
> -:- pred mlds_output_grade_var(io::di, io::uo) is det.
> +:- pred mlds_output_grade_check_fn_defn(mlds_module_name::in, io::di, io::uo) is det.
> 
> -mlds_output_grade_var(!IO) :-
> +mlds_output_grade_check_fn_defn(ModuleName, !IO) :-
>      io.write_string(
> -        "/* ensure everything is compiled with the same grade */\n",
> +        "// Ensure everything is compiled with the same grade.\n",
>          !IO),
> -    io.write_string(
> -        "static const void *const MR_grade = &MR_GRADE_VAR;\n",
> -        !IO).
> +    output_grade_check_fn_name(ModuleName, !IO),
> +    io.write_string("\n{\n", !IO),
> +    io.write_string("    return &MR_GRADE_VAR;\n", !IO),
> +    io.write_string("}\n", !IO).
> 
>      % Get the foreign code for C.
>      %
> @@ -729,7 +730,9 @@ mlds_output_init_fn_decls(ModuleName, InitPreds, FinalPreds, !IO) :-
>          FinalPreds = [_ | _],
>          output_required_fn_name(ModuleName, "required_final", !IO),
>          io.write_string(";\n", !IO)
> -    ).
> +    ),
> +    output_grade_check_fn_name(ModuleName, !IO),
> +    io.write_string(";\n", !IO).
> 
>  :- pred mlds_output_init_fn_defns(mlds_to_c_opts::in, mlds_module_name::in,
>      list(mlds_defn)::in, list(mlds_defn)::in,
> @@ -847,6 +850,20 @@ output_required_fn_name(ModuleName, Suffix, !IO) :-
>      io.write_string(Suffix, !IO),
>      io.write_string("(void)", !IO).
> 
> +:- pred output_grade_check_fn_name(mlds_module_name::in,
> +    io::di, io::uo) is det.
> +
> +output_grade_check_fn_name(ModuleName, !IO) :-
> +    ModuleNameString0 = sym_name_mangle(
> +        mlds_module_name_to_sym_name(ModuleName)),
> +    ( if string.prefix(ModuleNameString0, "mercury__") then
> +        ModuleNameString = ModuleNameString0
> +    else
> +        ModuleNameString = "mercury__" ++ ModuleNameString0
> +    ),
> +    io.format("const char *%s__grade_check(void)",
> +        [s(ModuleNameString)], !IO).
> +
>      % Generate calls to MR_init_entry() for the specified functions.
>      %
>  :- pred mlds_output_calls_to_init_entry(mlds_module_name::in,
> diff --git a/util/mkinit.c b/util/mkinit.c
> index 0e15a60..cbaa5b6 100644
> --- a/util/mkinit.c
> +++ b/util/mkinit.c
> @@ -619,9 +619,12 @@ static const char mercury_main_func[] =
>      "\n"
>      ;
> 
> -static const char mercury_grade_var[] =
> -    "/* ensure that everything gets compiled in the same grade */\n"
> -    "static const void *const MR_grade = &MR_GRADE_VAR;\n"
> +static const char mercury_grade_check_func[] =
> +    "// Ensure that everything gets compiled in the same grade.\n"
> +    "const char *mercury_init_grade_check(void)\n"
> +    "{\n"
> +    "    return &MR_GRADE_VAR;\n"
> +    "}\n"
>      "\n"
>      ;
> 
> @@ -1201,7 +1204,7 @@ output_main(void)
>          fputs(mercury_main_func, stdout);
>      }
> 
> -    fputs(mercury_grade_var, stdout);
> +    fputs(mercury_grade_check_func, stdout);
> 
>      if (output_main_func) {
>          fputs(main_func, stdout);
> _______________________________________________
> reviews mailing list
> reviews at lists.mercurylang.org
> https://lists.mercurylang.org/listinfo/reviews

-- 
Paul Bone


More information about the reviews mailing list