diff --git a/src/libgetopts/lib.rs b/src/libgetopts/lib.rs
index c9b8ed36391..b1b8351b040 100644
--- a/src/libgetopts/lib.rs
+++ b/src/libgetopts/lib.rs
@@ -455,6 +455,25 @@ pub fn optmulti(short_name: &str, long_name: &str, desc: &str, hint: &str) -> Op
     }
 }
 
+/// Create a generic option group, stating all parameters explicitly
+pub fn opt(short_name: &str,
+           long_name: &str,
+           desc: &str,
+           hint: &str,
+           hasarg: HasArg,
+           occur: Occur) -> OptGroup {
+    let len = short_name.len();
+    assert!(len == 1 || len == 0);
+    OptGroup {
+        short_name: short_name.to_owned(),
+        long_name: long_name.to_owned(),
+        hint: hint.to_owned(),
+        desc: desc.to_owned(),
+        hasarg: hasarg,
+        occur: occur
+    }
+}
+
 impl Fail_ {
     /// Convert a `Fail_` enum into an error string.
     pub fn to_err_msg(self) -> ~str {
diff --git a/src/librustc/back/link.rs b/src/librustc/back/link.rs
index 3a1c646144b..09e5b99fc23 100644
--- a/src/librustc/back/link.rs
+++ b/src/librustc/back/link.rs
@@ -12,7 +12,7 @@ use back::archive::{Archive, METADATA_FILENAME};
 use back::rpath;
 use back::svh::Svh;
 use driver::driver::{CrateTranslation, OutputFilenames};
-use driver::session::Session;
+use driver::session::{NoDebugInfo, Session};
 use driver::session;
 use lib::llvm::llvm;
 use lib::llvm::ModuleRef;
@@ -92,7 +92,7 @@ pub mod write {
     use back::link::{OutputTypeExe, OutputTypeLlvmAssembly};
     use back::link::{OutputTypeObject};
     use driver::driver::{CrateTranslation, OutputFilenames};
-    use driver::session::Session;
+    use driver::session::{NoDebugInfo, Session};
     use driver::session;
     use lib::llvm::llvm;
     use lib::llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
@@ -148,7 +148,7 @@ pub mod write {
 
             // FIXME: #11906: Omitting frame pointers breaks retrieving the value of a parameter.
             // FIXME: #11954: mac64 unwinding may not work with fp elim
-            let no_fp_elim = sess.opts.debuginfo ||
+            let no_fp_elim = (sess.opts.debuginfo != NoDebugInfo) ||
                              (sess.targ_cfg.os == abi::OsMacos &&
                               sess.targ_cfg.arch == abi::X86_64);
 
@@ -1052,7 +1052,7 @@ fn link_natively(sess: Session, dylib: bool, obj_filename: &Path,
 
     // On OSX, debuggers need this utility to get run to do some munging of
     // the symbols
-    if sess.targ_cfg.os == abi::OsMacos && sess.opts.debuginfo {
+    if sess.targ_cfg.os == abi::OsMacos && (sess.opts.debuginfo != NoDebugInfo) {
         // FIXME (#9639): This needs to handle non-utf8 paths
         match Process::status("dsymutil",
                                   [out_filename.as_str().unwrap().to_owned()]) {
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 88526dd15a9..c4f3bb21059 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -11,7 +11,8 @@
 
 use back::link;
 use back::{arm, x86, x86_64, mips};
-use driver::session::{Aggressive, CrateTypeExecutable};
+use driver::session::{Aggressive, CrateTypeExecutable, FullDebugInfo, LimitedDebugInfo,
+                      NoDebugInfo};
 use driver::session::{Session, Session_, No, Less, Default};
 use driver::session;
 use front;
@@ -38,7 +39,9 @@ use std::vec;
 use std::vec_ng::Vec;
 use std::vec_ng;
 use collections::{HashMap, HashSet};
-use getopts::{optopt, optmulti, optflag, optflagopt};
+use getopts::{optopt, optmulti, optflag, optflagopt, opt};
+use MaybeHasArg = getopts::Maybe;
+use OccurOptional = getopts::Optional;
 use getopts;
 use syntax::ast;
 use syntax::abi;
@@ -865,7 +868,18 @@ pub fn build_session_options(matches: &getopts::Matches)
         } else { No }
     };
     let gc = debugging_opts & session::GC != 0;
-    let debuginfo = matches.opt_present("g") || matches.opt_present("debuginfo");
+
+    let debuginfo = match matches.opt_default("debuginfo", "2") {
+        Some(level) => {
+            match level {
+                ~"0" => NoDebugInfo,
+                ~"1" => LimitedDebugInfo,
+                ~"2" => FullDebugInfo,
+                _    => early_error("debug info level needs to be between 0-2")
+            }
+        }
+        None => NoDebugInfo
+    };
 
     let addl_lib_search_paths = matches.opt_strs("L").map(|s| {
         Path::new(s.as_slice())
@@ -1012,61 +1026,47 @@ pub fn optgroups() -> ~[getopts::OptGroup] {
   optflag("h", "help", "Display this message"),
   optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
   optmulti("L", "",   "Add a directory to the library search path", "PATH"),
-  optmulti("", "crate-type", "Comma separated list of types of crates for the \
-                              compiler to emit",
+  optmulti("", "crate-type", "Comma separated list of types of crates for the compiler to emit",
            "[bin|lib|rlib|dylib|staticlib]"),
-  optmulti("", "emit", "Comma separated list of types of output for the compiler
-                        to emit",
+  optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
            "[asm|bc|ir|obj|link]"),
   optflag("", "crate-id", "Output the crate id and exit"),
   optflag("", "crate-name", "Output the crate name and exit"),
   optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
           continued and exit"),
   optflag("",  "ls",  "List the symbols defined by a library crate"),
-  optflag("g",  "debuginfo",  "Emit DWARF debug info to the objects created"),
-  optflag("", "no-trans",
-                        "Run all passes except translation; no output"),
-  optflag("", "no-analysis",
-                        "Parse and expand the output, but run no analysis or produce \
-                        output"),
-  optflag("O", "",    "Equivalent to --opt-level=2"),
-  optopt("o", "",     "Write output to <filename>", "FILENAME"),
-  optopt("", "opt-level",
-                        "Optimize with possible levels 0-3", "LEVEL"),
-  optopt( "",  "out-dir",
-                        "Write output to compiler-chosen filename
-                          in <dir>", "DIR"),
-  optflag("", "parse-only",
-                        "Parse only; do not compile, assemble, or link"),
+  opt("g",  "debuginfo",  "Emit DWARF debug info to the objects created:
+       0 = no debug info,
+       1 = line-tables only (for stacktraces),
+       2 = full debug info with variable, argument and type information",
+      "LEVEL", MaybeHasArg, OccurOptional),
+  optflag("", "no-trans", "Run all passes except translation; no output"),
+  optflag("", "no-analysis", "Parse and expand the output, but run no analysis or produce output"),
+  optflag("O", "", "Equivalent to --opt-level=2"),
+  optopt("o", "", "Write output to <filename>", "FILENAME"),
+  optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
+  optopt( "",  "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
+  optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
   optflagopt("", "pretty",
-                        "Pretty-print the input instead of compiling;
-                          valid types are: normal (un-annotated source),
-                          expanded (crates expanded),
-                          typed (crates expanded, with type annotations),
-                          or identified (fully parenthesized,
-                          AST nodes and blocks with IDs)", "TYPE"),
-  optflagopt("", "dep-info",
-                        "Output dependency info to <filename> after compiling", "FILENAME"),
-  optopt("", "sysroot",
-                        "Override the system root", "PATH"),
+             "Pretty-print the input instead of compiling;
+              valid types are: normal (un-annotated source),
+              expanded (crates expanded),
+              typed (crates expanded, with type annotations),
+              or identified (fully parenthesized,
+              AST nodes and blocks with IDs)", "TYPE"),
+  optflagopt("", "dep-info", "Output dependency info to <filename> after compiling", "FILENAME"),
+  optopt("", "sysroot", "Override the system root", "PATH"),
   optflag("", "test", "Build a test harness"),
-  optopt("", "target",
-                        "Target triple cpu-manufacturer-kernel[-os]
-                          to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
-                          for details)", "TRIPLE"),
-  optmulti("W", "warn",
-                        "Set lint warnings", "OPT"),
-  optmulti("A", "allow",
-                        "Set lint allowed", "OPT"),
-  optmulti("D", "deny",
-                        "Set lint denied", "OPT"),
-  optmulti("F", "forbid",
-                        "Set lint forbidden", "OPT"),
-  optmulti("C", "codegen",
-                        "Set a codegen option", "OPT[=VALUE]"),
-  optmulti("Z", "",   "Set internal debugging options", "FLAG"),
-  optflag( "v", "version",
-                        "Print version info and exit"),
+  optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
+                        to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
+                        for details)", "TRIPLE"),
+  optmulti("W", "warn", "Set lint warnings", "OPT"),
+  optmulti("A", "allow", "Set lint allowed", "OPT"),
+  optmulti("D", "deny", "Set lint denied", "OPT"),
+  optmulti("F", "forbid", "Set lint forbidden", "OPT"),
+  optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
+  optmulti("Z", "", "Set internal debugging options", "FLAG"),
+  optflag( "v", "version", "Print version info and exit"),
  ]
 }
 
diff --git a/src/librustc/driver/session.rs b/src/librustc/driver/session.rs
index d404360bf14..10d910636fc 100644
--- a/src/librustc/driver/session.rs
+++ b/src/librustc/driver/session.rs
@@ -114,6 +114,13 @@ pub enum OptLevel {
     Aggressive // -O3
 }
 
+#[deriving(Clone, Eq)]
+pub enum DebugInfoLevel {
+    NoDebugInfo,
+    LimitedDebugInfo,
+    FullDebugInfo,
+}
+
 #[deriving(Clone)]
 pub struct Options {
     // The crate config requested for the session, which may be combined
@@ -122,7 +129,7 @@ pub struct Options {
 
     gc: bool,
     optimize: OptLevel,
-    debuginfo: bool,
+    debuginfo: DebugInfoLevel,
     lint_opts: ~[(lint::Lint, lint::level)],
     output_types: ~[back::link::OutputType],
     // This was mutable for rustpkg, which updates search paths based on the
@@ -314,7 +321,7 @@ pub fn basic_options() -> @Options {
         crate_types: ~[],
         gc: false,
         optimize: No,
-        debuginfo: false,
+        debuginfo: NoDebugInfo,
         lint_opts: ~[],
         output_types: ~[],
         addl_lib_search_paths: @RefCell::new(HashSet::new()),
diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs
index 6247577c1a3..13104cfa40a 100644
--- a/src/librustc/middle/trans/_match.rs
+++ b/src/librustc/middle/trans/_match.rs
@@ -195,6 +195,7 @@
 #[allow(non_camel_case_types)];
 
 use back::abi;
+use driver::session::FullDebugInfo;
 use lib::llvm::{llvm, ValueRef, BasicBlockRef};
 use middle::const_eval;
 use middle::borrowck::root_map_key;
@@ -1393,7 +1394,7 @@ fn insert_lllocals<'a>(bcx: &'a Block<'a>,
             llmap.get().insert(binding_info.id, datum);
         }
 
-        if bcx.sess().opts.debuginfo {
+        if bcx.sess().opts.debuginfo == FullDebugInfo {
             debuginfo::create_match_binding_metadata(bcx,
                                                      ident,
                                                      binding_info.id,
@@ -2052,7 +2053,7 @@ pub fn store_arg<'a>(mut bcx: &'a Block<'a>,
             // like `x: T`
             let arg_ty = node_id_type(bcx, pat.id);
             if type_of::arg_is_indirect(bcx.ccx(), arg_ty)
-                && !bcx.ccx().sess.opts.debuginfo {
+                && bcx.ccx().sess.opts.debuginfo != FullDebugInfo {
                 // Don't copy an indirect argument to an alloca, the caller
                 // already put it in a temporary alloca and gave it up, unless
                 // we emit extra-debug-info, which requires local allocas :(.
diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs
index f838bcf9c5e..b9d5eb851b9 100644
--- a/src/librustc/middle/trans/base.rs
+++ b/src/librustc/middle/trans/base.rs
@@ -28,7 +28,7 @@
 use back::link::{mangle_exported_name};
 use back::{link, abi};
 use driver::session;
-use driver::session::Session;
+use driver::session::{Session, NoDebugInfo, FullDebugInfo};
 use driver::driver::OutputFilenames;
 use driver::driver::{CrateAnalysis, CrateTranslation};
 use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
@@ -1367,7 +1367,7 @@ fn copy_args_to_allocas<'a>(fcx: &FunctionContext<'a>,
 
         bcx = _match::store_arg(bcx, args[i].pat, arg_datum, arg_scope_id);
 
-        if fcx.ccx.sess.opts.debuginfo {
+        if fcx.ccx.sess.opts.debuginfo == FullDebugInfo {
             debuginfo::create_argument_metadata(bcx, &args[i]);
         }
     }
@@ -2678,7 +2678,7 @@ pub fn trans_crate(sess: session::Session,
     }
 
     glue::emit_tydescs(ccx);
-    if ccx.sess.opts.debuginfo {
+    if ccx.sess.opts.debuginfo != NoDebugInfo {
         debuginfo::finalize(ccx);
     }
 
diff --git a/src/librustc/middle/trans/closure.rs b/src/librustc/middle/trans/closure.rs
index 2be53b92db1..aabe19deefc 100644
--- a/src/librustc/middle/trans/closure.rs
+++ b/src/librustc/middle/trans/closure.rs
@@ -11,6 +11,7 @@
 
 use back::abi;
 use back::link::mangle_internal_name_by_path_and_seq;
+use driver::session::FullDebugInfo;
 use lib::llvm::ValueRef;
 use middle::moves;
 use middle::trans::base::*;
@@ -299,7 +300,7 @@ fn load_environment<'a>(bcx: &'a Block<'a>, cdata_ty: ty::t,
 
     // Store the pointer to closure data in an alloca for debug info because that's what the
     // llvm.dbg.declare intrinsic expects
-    let env_pointer_alloca = if bcx.ccx().sess.opts.debuginfo {
+    let env_pointer_alloca = if bcx.ccx().sess.opts.debuginfo == FullDebugInfo {
         let alloc = alloc_ty(bcx, ty::mk_mut_ptr(bcx.tcx(), cdata_ty), "__debuginfo_env_ptr");
         Store(bcx, llcdata, alloc);
         Some(alloc)
diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs
index b90fc4f6bbf..5011ee8be6e 100644
--- a/src/librustc/middle/trans/context.rs
+++ b/src/librustc/middle/trans/context.rs
@@ -10,6 +10,7 @@
 
 
 use driver::session;
+use driver::session::NoDebugInfo;
 use lib::llvm::{ContextRef, ModuleRef, ValueRef};
 use lib::llvm::{llvm, TargetData, TypeNames};
 use lib::llvm::mk_target_data;
@@ -151,7 +152,7 @@ impl CrateContext {
             let tn = TypeNames::new();
 
             let mut intrinsics = base::declare_intrinsics(llmod);
-            if sess.opts.debuginfo {
+            if sess.opts.debuginfo != NoDebugInfo {
                 base::declare_dbg_intrinsics(llmod, &mut intrinsics);
             }
             let int_type = Type::int(targ_cfg.arch);
@@ -165,7 +166,7 @@ impl CrateContext {
             tn.associate_type("str_slice", &str_slice_ty);
 
             let (crate_map_name, crate_map) = decl_crate_map(sess, link_meta.clone(), llmod);
-            let dbg_cx = if sess.opts.debuginfo {
+            let dbg_cx = if sess.opts.debuginfo != NoDebugInfo {
                 Some(debuginfo::CrateDebugContext::new(llmod))
             } else {
                 None
diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs
index 2aab8926223..215f36a776d 100644
--- a/src/librustc/middle/trans/controlflow.rs
+++ b/src/librustc/middle/trans/controlflow.rs
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use lib::llvm::*;
+use driver::session::FullDebugInfo;
 use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem};
 use middle::trans::base::*;
 use middle::trans::build::*;
@@ -54,7 +55,7 @@ pub fn trans_stmt<'a>(cx: &'a Block<'a>,
             match d.node {
                 ast::DeclLocal(ref local) => {
                     bcx = init_local(bcx, *local);
-                    if cx.sess().opts.debuginfo {
+                    if cx.sess().opts.debuginfo == FullDebugInfo {
                         debuginfo::create_local_var_metadata(bcx, *local);
                     }
                 }
diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs
index fef559698ab..e88319e6d67 100644
--- a/src/librustc/middle/trans/debuginfo.rs
+++ b/src/librustc/middle/trans/debuginfo.rs
@@ -126,6 +126,7 @@ is still disabled, so there is no need to do anything special with source locati
 
 
 use driver::session;
+use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use lib::llvm::llvm;
 use lib::llvm::{ModuleRef, ContextRef, ValueRef};
 use lib::llvm::debuginfo::*;
@@ -530,7 +531,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
                                      fn_ast_id: ast::NodeId,
                                      param_substs: Option<@param_substs>,
                                      llfn: ValueRef) -> FunctionDebugContext {
-    if !cx.sess.opts.debuginfo {
+    if cx.sess.opts.debuginfo == NoDebugInfo {
         return DebugInfoDisabled;
     }
 
@@ -706,7 +707,7 @@ pub fn create_function_debug_context(cx: &CrateContext,
                               fn_decl: &ast::FnDecl,
                               param_substs: Option<@param_substs>,
                               error_span: Span) -> DIArray {
-        if !cx.sess.opts.debuginfo {
+        if cx.sess.opts.debuginfo == LimitedDebugInfo {
             return create_DIArray(DIB(cx), []);
         }
 
@@ -783,8 +784,8 @@ pub fn create_function_debug_context(cx: &CrateContext,
                 name_to_append_suffix_to.push_str(",");
             }
 
-            // Only create type information if debuginfo is enabled
-            if cx.sess.opts.debuginfo {
+            // Only create type information if full debuginfo is enabled
+            if cx.sess.opts.debuginfo == FullDebugInfo {
                 let actual_self_type_metadata = type_metadata(cx,
                                                               actual_self_type,
                                                               codemap::DUMMY_SP);
@@ -827,8 +828,8 @@ pub fn create_function_debug_context(cx: &CrateContext,
                 name_to_append_suffix_to.push_str(",");
             }
 
-            // Again, only create type information if debuginfo is enabled
-            if cx.sess.opts.debuginfo {
+            // Again, only create type information if full debuginfo is enabled
+            if cx.sess.opts.debuginfo == FullDebugInfo {
                 let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
                 let param_metadata = token::get_ident(ident).get()
                                                             .with_c_str(|name| {
diff --git a/src/test/debug-info/issue7712.rs b/src/test/debug-info/issue7712.rs
index f91112416e3..af9b84085e3 100644
--- a/src/test/debug-info/issue7712.rs
+++ b/src/test/debug-info/issue7712.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// compile-flags:-g
+// compile-flags:-g1
 
 pub trait TraitWithDefaultMethod {
     fn method(self) {
diff --git a/src/test/debug-info/lexical-scope-in-parameterless-closure.rs b/src/test/debug-info/lexical-scope-in-parameterless-closure.rs
index f0cb670a23c..ec2c80034d2 100644
--- a/src/test/debug-info/lexical-scope-in-parameterless-closure.rs
+++ b/src/test/debug-info/lexical-scope-in-parameterless-closure.rs
@@ -10,7 +10,7 @@
 
 // ignore-android: FIXME(#10381)
 
-// compile-flags:-g
+// compile-flags:-g1
 // debugger:run
 
 // Nothing to do here really, just make sure it compiles. See issue #8513.
diff --git a/src/test/debug-info/limited-debuginfo.rs b/src/test/debug-info/limited-debuginfo.rs
new file mode 100644
index 00000000000..ccf1506a565
--- /dev/null
+++ b/src/test/debug-info/limited-debuginfo.rs
@@ -0,0 +1,52 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-android: FIXME(#10381)
+
+// compile-flags:-g1
+
+// Make sure functions have proper names
+// debugger:info functions
+// check:static void limited-debuginfo::main();
+// check:static void limited-debuginfo::some_function();
+// check:static void limited-debuginfo::some_other_function();
+// check:static void limited-debuginfo::zzz();
+
+// debugger:rbreak zzz
+// debugger:run
+
+// Make sure there is no information about locals
+// debugger:finish
+// debugger:info locals
+// check:No locals.
+// debugger:continue
+
+
+#[allow(unused_variable)];
+
+struct Struct {
+    a: i64,
+    b: i32
+}
+
+fn main() {
+    some_function(101, 202);
+}
+
+
+fn zzz() {()}
+
+fn some_function(a: int, b: int) {
+    let some_variable = Struct { a: 11, b: 22 };
+    let some_other_variable = 23;
+    zzz();
+}
+
+fn some_other_function(a: int, b: int) -> bool { true }
\ No newline at end of file